Skip to content

Commit c1b08dd

Browse files
committedAug 19, 2019
Auto merge of #63715 - Centril:rollup-dga8qtp, r=Centril
Rollup of 5 pull requests Successful merges: - #63252 (Remove recommendation about idiomatic syntax for Arc::clone) - #63376 (use different lifetime name for object-lifetime-default elision) - #63620 (Use constraint span when lowering associated types) - #63699 (Fix suggestion from incorrect `move async` to `async move`.) - #63704 ( Fixed: error: unnecessary trailing semicolon) Failed merges: r? @ghost
2 parents 29a5403 + ac34594 commit c1b08dd

33 files changed

+847
-219
lines changed
 

‎src/liballoc/sync.rs

-4
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,6 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize;
107107
/// // a, b, and foo are all Arcs that point to the same memory location
108108
/// ```
109109
///
110-
/// The [`Arc::clone(&from)`] syntax is the most idiomatic because it conveys more explicitly
111-
/// the meaning of the code. In the example above, this syntax makes it easier to see that
112-
/// this code is creating a new reference rather than copying the whole content of foo.
113-
///
114110
/// ## `Deref` behavior
115111
///
116112
/// `Arc<T>` automatically dereferences to `T` (via the [`Deref`][deref] trait),

‎src/librustc/hir/intravisit.rs

+1
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,7 @@ pub fn walk_lifetime<'v, V: Visitor<'v>>(visitor: &mut V, lifetime: &'v Lifetime
433433
LifetimeName::Static |
434434
LifetimeName::Error |
435435
LifetimeName::Implicit |
436+
LifetimeName::ImplicitObjectLifetimeDefault |
436437
LifetimeName::Underscore => {}
437438
}
438439
}

‎src/librustc/hir/lowering.rs

+71-15
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ use syntax::symbol::{kw, sym, Symbol};
7272
use syntax::tokenstream::{TokenStream, TokenTree};
7373
use syntax::parse::token::{self, Token};
7474
use syntax::visit::{self, Visitor};
75-
use syntax_pos::{DUMMY_SP, Span};
75+
use syntax_pos::Span;
7676

7777
const HIR_ID_COUNTER_LOCKED: u32 = 0xFFFFFFFF;
7878

@@ -322,7 +322,7 @@ enum ParenthesizedGenericArgs {
322322
/// `resolve_lifetime` module. Often we "fallthrough" to that code by generating
323323
/// an "elided" or "underscore" lifetime name. In the future, we probably want to move
324324
/// everything into HIR lowering.
325-
#[derive(Copy, Clone)]
325+
#[derive(Copy, Clone, Debug)]
326326
enum AnonymousLifetimeMode {
327327
/// For **Modern** cases, create a new anonymous region parameter
328328
/// and reference that.
@@ -715,10 +715,16 @@ impl<'a> LoweringContext<'a> {
715715
anonymous_lifetime_mode: AnonymousLifetimeMode,
716716
op: impl FnOnce(&mut Self) -> R,
717717
) -> R {
718+
debug!(
719+
"with_anonymous_lifetime_mode(anonymous_lifetime_mode={:?})",
720+
anonymous_lifetime_mode,
721+
);
718722
let old_anonymous_lifetime_mode = self.anonymous_lifetime_mode;
719723
self.anonymous_lifetime_mode = anonymous_lifetime_mode;
720724
let result = op(self);
721725
self.anonymous_lifetime_mode = old_anonymous_lifetime_mode;
726+
debug!("with_anonymous_lifetime_mode: restoring anonymous_lifetime_mode={:?}",
727+
old_anonymous_lifetime_mode);
722728
result
723729
}
724730

@@ -1033,13 +1039,14 @@ impl<'a> LoweringContext<'a> {
10331039
/// ```
10341040
///
10351041
/// returns a `hir::TypeBinding` representing `Item`.
1036-
fn lower_assoc_ty_constraint(&mut self,
1037-
c: &AssocTyConstraint,
1038-
itctx: ImplTraitContext<'_>)
1039-
-> hir::TypeBinding {
1040-
debug!("lower_assoc_ty_constraint(constraint={:?}, itctx={:?})", c, itctx);
1042+
fn lower_assoc_ty_constraint(
1043+
&mut self,
1044+
constraint: &AssocTyConstraint,
1045+
itctx: ImplTraitContext<'_>,
1046+
) -> hir::TypeBinding {
1047+
debug!("lower_assoc_ty_constraint(constraint={:?}, itctx={:?})", constraint, itctx);
10411048

1042-
let kind = match c.kind {
1049+
let kind = match constraint.kind {
10431050
AssocTyConstraintKind::Equality { ref ty } => hir::TypeBindingKind::Equality {
10441051
ty: self.lower_ty(ty, itctx)
10451052
},
@@ -1094,15 +1101,15 @@ impl<'a> LoweringContext<'a> {
10941101
impl_trait_node_id,
10951102
DefPathData::ImplTrait,
10961103
ExpnId::root(),
1097-
DUMMY_SP
1104+
constraint.span,
10981105
);
10991106

11001107
self.with_dyn_type_scope(false, |this| {
11011108
let ty = this.lower_ty(
11021109
&Ty {
11031110
id: this.sess.next_node_id(),
11041111
node: TyKind::ImplTrait(impl_trait_node_id, bounds.clone()),
1105-
span: DUMMY_SP,
1112+
span: constraint.span,
11061113
},
11071114
itctx,
11081115
);
@@ -1124,10 +1131,10 @@ impl<'a> LoweringContext<'a> {
11241131
};
11251132

11261133
hir::TypeBinding {
1127-
hir_id: self.lower_node_id(c.id),
1128-
ident: c.ident,
1134+
hir_id: self.lower_node_id(constraint.id),
1135+
ident: constraint.ident,
11291136
kind,
1130-
span: c.span,
1137+
span: constraint.span,
11311138
}
11321139
}
11331140

@@ -1355,6 +1362,13 @@ impl<'a> LoweringContext<'a> {
13551362
opaque_ty_node_id: NodeId,
13561363
lower_bounds: impl FnOnce(&mut LoweringContext<'_>) -> hir::GenericBounds,
13571364
) -> hir::TyKind {
1365+
debug!(
1366+
"lower_opaque_impl_trait(fn_def_id={:?}, opaque_ty_node_id={:?}, span={:?})",
1367+
fn_def_id,
1368+
opaque_ty_node_id,
1369+
span,
1370+
);
1371+
13581372
// Make sure we know that some funky desugaring has been going on here.
13591373
// This is a first: there is code in other places like for loop
13601374
// desugaring that explicitly states that we don't want to track that.
@@ -1382,6 +1396,14 @@ impl<'a> LoweringContext<'a> {
13821396
&hir_bounds,
13831397
);
13841398

1399+
debug!(
1400+
"lower_opaque_impl_trait: lifetimes={:#?}", lifetimes,
1401+
);
1402+
1403+
debug!(
1404+
"lower_opaque_impl_trait: lifetime_defs={:#?}", lifetime_defs,
1405+
);
1406+
13851407
self.with_hir_id_owner(opaque_ty_node_id, |lctx| {
13861408
let opaque_ty_item = hir::OpaqueTy {
13871409
generics: hir::Generics {
@@ -1397,7 +1419,7 @@ impl<'a> LoweringContext<'a> {
13971419
origin: hir::OpaqueTyOrigin::FnReturn,
13981420
};
13991421

1400-
trace!("exist ty from impl trait def-index: {:#?}", opaque_ty_def_index);
1422+
trace!("lower_opaque_impl_trait: {:#?}", opaque_ty_def_index);
14011423
let opaque_ty_id = lctx.generate_opaque_type(
14021424
opaque_ty_node_id,
14031425
opaque_ty_item,
@@ -1445,6 +1467,13 @@ impl<'a> LoweringContext<'a> {
14451467
parent_index: DefIndex,
14461468
bounds: &hir::GenericBounds,
14471469
) -> (HirVec<hir::GenericArg>, HirVec<hir::GenericParam>) {
1470+
debug!(
1471+
"lifetimes_from_impl_trait_bounds(opaque_ty_id={:?}, \
1472+
parent_index={:?}, \
1473+
bounds={:#?})",
1474+
opaque_ty_id, parent_index, bounds,
1475+
);
1476+
14481477
// This visitor walks over `impl Trait` bounds and creates defs for all lifetimes that
14491478
// appear in the bounds, excluding lifetimes that are created within the bounds.
14501479
// E.g., `'a`, `'b`, but not `'c` in `impl for<'c> SomeTrait<'a, 'b, 'c>`.
@@ -1532,6 +1561,11 @@ impl<'a> LoweringContext<'a> {
15321561
}
15331562
}
15341563
hir::LifetimeName::Param(_) => lifetime.name,
1564+
1565+
// Refers to some other lifetime that is "in
1566+
// scope" within the type.
1567+
hir::LifetimeName::ImplicitObjectLifetimeDefault => return,
1568+
15351569
hir::LifetimeName::Error | hir::LifetimeName::Static => return,
15361570
};
15371571

@@ -2182,6 +2216,14 @@ impl<'a> LoweringContext<'a> {
21822216
fn_def_id: DefId,
21832217
opaque_ty_node_id: NodeId,
21842218
) -> hir::FunctionRetTy {
2219+
debug!(
2220+
"lower_async_fn_ret_ty(\
2221+
output={:?}, \
2222+
fn_def_id={:?}, \
2223+
opaque_ty_node_id={:?})",
2224+
output, fn_def_id, opaque_ty_node_id,
2225+
);
2226+
21852227
let span = output.span();
21862228

21872229
let opaque_ty_span = self.mark_span_with_reason(
@@ -2264,6 +2306,8 @@ impl<'a> LoweringContext<'a> {
22642306
),
22652307
);
22662308

2309+
debug!("lower_async_fn_ret_ty: future_bound={:#?}", future_bound);
2310+
22672311
// Calculate all the lifetimes that should be captured
22682312
// by the opaque type. This should include all in-scope
22692313
// lifetime parameters, including those defined in-band.
@@ -2512,6 +2556,12 @@ impl<'a> LoweringContext<'a> {
25122556
hir::LifetimeName::Implicit
25132557
| hir::LifetimeName::Underscore
25142558
| hir::LifetimeName::Static => hir::ParamName::Plain(lt.name.ident()),
2559+
hir::LifetimeName::ImplicitObjectLifetimeDefault => {
2560+
span_bug!(
2561+
param.ident.span,
2562+
"object-lifetime-default should not occur here",
2563+
);
2564+
}
25152565
hir::LifetimeName::Error => ParamName::Error,
25162566
};
25172567

@@ -3255,7 +3305,13 @@ impl<'a> LoweringContext<'a> {
32553305
AnonymousLifetimeMode::PassThrough => {}
32563306
}
32573307

3258-
self.new_implicit_lifetime(span)
3308+
let r = hir::Lifetime {
3309+
hir_id: self.next_id(),
3310+
span,
3311+
name: hir::LifetimeName::ImplicitObjectLifetimeDefault,
3312+
};
3313+
debug!("elided_dyn_bound: r={:?}", r);
3314+
r
32593315
}
32603316

32613317
fn new_implicit_lifetime(&mut self, span: Span) -> hir::Lifetime {

‎src/librustc/hir/mod.rs

+19-2
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,19 @@ pub enum LifetimeName {
221221
/// User wrote nothing (e.g., the lifetime in `&u32`).
222222
Implicit,
223223

224+
/// Implicit lifetime in a context like `dyn Foo`. This is
225+
/// distinguished from implicit lifetimes elsewhere because the
226+
/// lifetime that they default to must appear elsewhere within the
227+
/// enclosing type. This means that, in an `impl Trait` context, we
228+
/// don't have to create a parameter for them. That is, `impl
229+
/// Trait<Item = &u32>` expands to an opaque type like `type
230+
/// Foo<'a> = impl Trait<Item = &'a u32>`, but `impl Trait<item =
231+
/// dyn Bar>` expands to `type Foo = impl Trait<Item = dyn Bar +
232+
/// 'static>`. The latter uses `ImplicitObjectLifetimeDefault` so
233+
/// that surrounding code knows not to create a lifetime
234+
/// parameter.
235+
ImplicitObjectLifetimeDefault,
236+
224237
/// Indicates an error during lowering (usually `'_` in wrong place)
225238
/// that was already reported.
226239
Error,
@@ -235,7 +248,9 @@ pub enum LifetimeName {
235248
impl LifetimeName {
236249
pub fn ident(&self) -> Ident {
237250
match *self {
238-
LifetimeName::Implicit | LifetimeName::Error => Ident::invalid(),
251+
LifetimeName::ImplicitObjectLifetimeDefault
252+
| LifetimeName::Implicit
253+
| LifetimeName::Error => Ident::invalid(),
239254
LifetimeName::Underscore => Ident::with_dummy_span(kw::UnderscoreLifetime),
240255
LifetimeName::Static => Ident::with_dummy_span(kw::StaticLifetime),
241256
LifetimeName::Param(param_name) => param_name.ident(),
@@ -244,7 +259,9 @@ impl LifetimeName {
244259

245260
pub fn is_elided(&self) -> bool {
246261
match self {
247-
LifetimeName::Implicit | LifetimeName::Underscore => true,
262+
LifetimeName::ImplicitObjectLifetimeDefault
263+
| LifetimeName::Implicit
264+
| LifetimeName::Underscore => true,
248265

249266
// It might seem surprising that `Fresh(_)` counts as
250267
// *not* elided -- but this is because, as far as the code

‎src/librustc/infer/opaque_types/mod.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
127127
) -> InferOk<'tcx, (T, OpaqueTypeMap<'tcx>)> {
128128
debug!(
129129
"instantiate_opaque_types(value={:?}, parent_def_id={:?}, body_id={:?}, \
130-
param_env={:?})",
131-
value, parent_def_id, body_id, param_env,
130+
param_env={:?}, value_span={:?})",
131+
value, parent_def_id, body_id, param_env, value_span,
132132
);
133133
let mut instantiator = Instantiator {
134134
infcx: self,
@@ -1108,9 +1108,11 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
11081108
// Use the same type variable if the exact same opaque type appears more
11091109
// than once in the return type (e.g., if it's passed to a type alias).
11101110
if let Some(opaque_defn) = self.opaque_types.get(&def_id) {
1111+
debug!("instantiate_opaque_types: returning concrete ty {:?}", opaque_defn.concrete_ty);
11111112
return opaque_defn.concrete_ty;
11121113
}
11131114
let span = tcx.def_span(def_id);
1115+
debug!("fold_opaque_ty {:?} {:?}", self.value_span, span);
11141116
let ty_var = infcx
11151117
.next_ty_var(TypeVariableOrigin { kind: TypeVariableOriginKind::TypeInference, span });
11161118

‎src/librustc/middle/resolve_lifetime.rs

+92-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
//! used between functions, and they operate in a purely top-down
66
//! way. Therefore, we break lifetime name resolution into a separate pass.
77
8+
// ignore-tidy-filelength
9+
810
use crate::hir::def::{Res, DefKind};
911
use crate::hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
1012
use crate::hir::map::Map;
@@ -556,6 +558,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
556558

557559
fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
558560
debug!("visit_ty: id={:?} ty={:?}", ty.hir_id, ty);
561+
debug!("visit_ty: ty.node={:?}", ty.node);
559562
match ty.node {
560563
hir::TyKind::BareFn(ref c) => {
561564
let next_early_index = self.next_early_index();
@@ -585,11 +588,20 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
585588
self.is_in_fn_syntax = was_in_fn_syntax;
586589
}
587590
hir::TyKind::TraitObject(ref bounds, ref lifetime) => {
591+
debug!("visit_ty: TraitObject(bounds={:?}, lifetime={:?})", bounds, lifetime);
588592
for bound in bounds {
589593
self.visit_poly_trait_ref(bound, hir::TraitBoundModifier::None);
590594
}
591595
match lifetime.name {
592596
LifetimeName::Implicit => {
597+
// For types like `dyn Foo`, we should
598+
// generate a special form of elided.
599+
span_bug!(
600+
ty.span,
601+
"object-lifetime-default expected, not implict",
602+
);
603+
}
604+
LifetimeName::ImplicitObjectLifetimeDefault => {
593605
// If the user does not write *anything*, we
594606
// use the object lifetime defaulting
595607
// rules. So e.g., `Box<dyn Debug>` becomes
@@ -897,6 +909,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
897909
}
898910

899911
fn visit_lifetime(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
912+
debug!("visit_lifetime(lifetime_ref={:?})", lifetime_ref);
900913
if lifetime_ref.is_elided() {
901914
self.resolve_elided_lifetimes(vec![lifetime_ref]);
902915
return;
@@ -1911,6 +1924,13 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
19111924
}
19121925

19131926
fn visit_segment_args(&mut self, res: Res, depth: usize, generic_args: &'tcx hir::GenericArgs) {
1927+
debug!(
1928+
"visit_segment_args(res={:?}, depth={:?}, generic_args={:?})",
1929+
res,
1930+
depth,
1931+
generic_args,
1932+
);
1933+
19141934
if generic_args.parenthesized {
19151935
let was_in_fn_syntax = self.is_in_fn_syntax;
19161936
self.is_in_fn_syntax = true;
@@ -1964,6 +1984,23 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
19641984
_ => None,
19651985
};
19661986

1987+
debug!("visit_segment_args: type_def_id={:?}", type_def_id);
1988+
1989+
// Compute a vector of defaults, one for each type parameter,
1990+
// per the rules given in RFCs 599 and 1156. Example:
1991+
//
1992+
// ```rust
1993+
// struct Foo<'a, T: 'a, U> { }
1994+
// ```
1995+
//
1996+
// If you have `Foo<'x, dyn Bar, dyn Baz>`, we want to default
1997+
// `dyn Bar` to `dyn Bar + 'x` (because of the `T: 'a` bound)
1998+
// and `dyn Baz` to `dyn Baz + 'static` (because there is no
1999+
// such bound).
2000+
//
2001+
// Therefore, we would compute `object_lifetime_defaults` to a
2002+
// vector like `['x, 'static]`. Note that the vector only
2003+
// includes type parameters.
19672004
let object_lifetime_defaults = type_def_id.map_or(vec![], |def_id| {
19682005
let in_body = {
19692006
let mut scope = self.scope;
@@ -2003,6 +2040,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
20032040
.collect()
20042041
})
20052042
};
2043+
debug!("visit_segment_args: unsubst={:?}", unsubst);
20062044
unsubst
20072045
.iter()
20082046
.map(|set| match *set {
@@ -2023,6 +2061,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
20232061
.collect()
20242062
});
20252063

2064+
debug!("visit_segment_args: object_lifetime_defaults={:?}", object_lifetime_defaults);
2065+
20262066
let mut i = 0;
20272067
for arg in &generic_args.args {
20282068
match arg {
@@ -2045,8 +2085,49 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
20452085
}
20462086
}
20472087

2088+
// Hack: when resolving the type `XX` in binding like `dyn
2089+
// Foo<'b, Item = XX>`, the current object-lifetime default
2090+
// would be to examine the trait `Foo` to check whether it has
2091+
// a lifetime bound declared on `Item`. e.g., if `Foo` is
2092+
// declared like so, then the default object lifetime bound in
2093+
// `XX` should be `'b`:
2094+
//
2095+
// ```rust
2096+
// trait Foo<'a> {
2097+
// type Item: 'a;
2098+
// }
2099+
// ```
2100+
//
2101+
// but if we just have `type Item;`, then it would be
2102+
// `'static`. However, we don't get all of this logic correct.
2103+
//
2104+
// Instead, we do something hacky: if there are no lifetime parameters
2105+
// to the trait, then we simply use a default object lifetime
2106+
// bound of `'static`, because there is no other possibility. On the other hand,
2107+
// if there ARE lifetime parameters, then we require the user to give an
2108+
// explicit bound for now.
2109+
//
2110+
// This is intended to leave room for us to implement the
2111+
// correct behavior in the future.
2112+
let has_lifetime_parameter = generic_args
2113+
.args
2114+
.iter()
2115+
.any(|arg| match arg {
2116+
GenericArg::Lifetime(_) => true,
2117+
_ => false,
2118+
});
2119+
2120+
// Resolve lifetimes found in the type `XX` from `Item = XX` bindings.
20482121
for b in &generic_args.bindings {
2049-
self.visit_assoc_type_binding(b);
2122+
let scope = Scope::ObjectLifetimeDefault {
2123+
lifetime: if has_lifetime_parameter {
2124+
None
2125+
} else {
2126+
Some(Region::Static)
2127+
},
2128+
s: self.scope,
2129+
};
2130+
self.with(scope, |_, this| this.visit_assoc_type_binding(b));
20502131
}
20512132
}
20522133

@@ -2347,6 +2428,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
23472428
}
23482429

23492430
fn resolve_elided_lifetimes(&mut self, lifetime_refs: Vec<&'tcx hir::Lifetime>) {
2431+
debug!("resolve_elided_lifetimes(lifetime_refs={:?})", lifetime_refs);
2432+
23502433
if lifetime_refs.is_empty() {
23512434
return;
23522435
}
@@ -2539,6 +2622,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
25392622
}
25402623

25412624
fn resolve_object_lifetime_default(&mut self, lifetime_ref: &'tcx hir::Lifetime) {
2625+
debug!("resolve_object_lifetime_default(lifetime_ref={:?})", lifetime_ref);
25422626
let mut late_depth = 0;
25432627
let mut scope = self.scope;
25442628
let lifetime = loop {
@@ -2638,6 +2722,13 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
26382722
hir::LifetimeName::Param(_) | hir::LifetimeName::Implicit => {
26392723
self.resolve_lifetime_ref(lt);
26402724
}
2725+
hir::LifetimeName::ImplicitObjectLifetimeDefault => {
2726+
self.tcx.sess.delay_span_bug(
2727+
lt.span,
2728+
"lowering generated `ImplicitObjectLifetimeDefault` \
2729+
outside of an object type",
2730+
)
2731+
}
26412732
hir::LifetimeName::Error => {
26422733
// No need to do anything, error already reported.
26432734
}

‎src/librustc/traits/fulfill.rs

+12-9
Original file line numberDiff line numberDiff line change
@@ -248,10 +248,10 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
248248
/// This is always inlined, despite its size, because it has a single
249249
/// callsite and it is called *very* frequently.
250250
#[inline(always)]
251-
fn process_obligation(&mut self,
252-
pending_obligation: &mut Self::Obligation)
253-
-> ProcessResult<Self::Obligation, Self::Error>
254-
{
251+
fn process_obligation(
252+
&mut self,
253+
pending_obligation: &mut Self::Obligation,
254+
) -> ProcessResult<Self::Obligation, Self::Error> {
255255
// if we were stalled on some unresolved variables, first check
256256
// whether any of them have been resolved; if not, don't bother
257257
// doing more work yet
@@ -277,7 +277,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
277277
self.selcx.infcx().resolve_vars_if_possible(&obligation.predicate);
278278
}
279279

280-
debug!("process_obligation: obligation = {:?}", obligation);
280+
debug!("process_obligation: obligation = {:?} cause = {:?}", obligation, obligation.cause);
281281

282282
match obligation.predicate {
283283
ty::Predicate::Trait(ref data) => {
@@ -425,10 +425,13 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
425425
}
426426

427427
ty::Predicate::WellFormed(ty) => {
428-
match ty::wf::obligations(self.selcx.infcx(),
429-
obligation.param_env,
430-
obligation.cause.body_id,
431-
ty, obligation.cause.span) {
428+
match ty::wf::obligations(
429+
self.selcx.infcx(),
430+
obligation.param_env,
431+
obligation.cause.body_id,
432+
ty,
433+
obligation.cause.span,
434+
) {
432435
None => {
433436
pending_obligation.stalled_on = vec![ty];
434437
ProcessResult::Unchanged

‎src/librustc_mir/borrow_check/conflict_errors.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -1190,7 +1190,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
11901190
);
11911191

11921192
let suggestion = match tcx.sess.source_map().span_to_snippet(args_span) {
1193-
Ok(string) => format!("move {}", string),
1193+
Ok(mut string) => {
1194+
if string.starts_with("async ") {
1195+
string.insert_str(6, "move ");
1196+
} else if string.starts_with("async|") {
1197+
string.insert_str(5, " move");
1198+
} else {
1199+
string.insert_str(0, "move ");
1200+
};
1201+
string
1202+
},
11941203
Err(_) => "move |<args>| <body>".to_string()
11951204
};
11961205

‎src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -578,7 +578,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
578578
})
579579
}
580580

581-
hir::LifetimeName::Implicit => {
581+
hir::LifetimeName::ImplicitObjectLifetimeDefault
582+
| hir::LifetimeName::Implicit => {
582583
// In this case, the user left off the lifetime; so
583584
// they wrote something like:
584585
//

‎src/libstd/sys/vxworks/process/process_common.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ impl Command {
155155
_f: Box<dyn FnMut() -> io::Result<()> + Send + Sync>,
156156
) {
157157
// Fork() is not supported in vxWorks so no way to run the closure in the new procecss.
158-
unimplemented!();;
158+
unimplemented!();
159159
}
160160

161161
pub fn stdin(&mut self, stdin: Stdio) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// This test documents that `type Out = Box<dyn Bar<Assoc: Copy>>;`
2+
// is allowed and will correctly reject an opaque `type Out` which
3+
// does not satisfy the bound `<TheType as Bar>::Assoc: Copy`.
4+
//
5+
// FIXME(rust-lang/lang): I think this behavior is logical if we want to allow
6+
// `dyn Trait<Assoc: Bound>` but we should decide if we want that. // Centril
7+
//
8+
// Additionally, as reported in https://github.com/rust-lang/rust/issues/63594,
9+
// we check that the spans for the error message are sane here.
10+
11+
#![feature(associated_type_bounds)]
12+
13+
fn main() {}
14+
15+
trait Bar { type Assoc; }
16+
17+
trait Thing {
18+
type Out;
19+
fn func() -> Self::Out;
20+
}
21+
22+
struct AssocNoCopy;
23+
impl Bar for AssocNoCopy { type Assoc = String; }
24+
25+
impl Thing for AssocNoCopy {
26+
type Out = Box<dyn Bar<Assoc: Copy>>;
27+
//~^ ERROR the trait bound `std::string::String: std::marker::Copy` is not satisfied
28+
29+
fn func() -> Self::Out {
30+
Box::new(AssocNoCopy)
31+
}
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0277]: the trait bound `std::string::String: std::marker::Copy` is not satisfied
2+
--> $DIR/assoc-type-eq-with-dyn-atb-fail.rs:26:28
3+
|
4+
LL | type Out = Box<dyn Bar<Assoc: Copy>>;
5+
| ^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `std::string::String`
6+
|
7+
= note: the return type of a function must have a statically known size
8+
9+
error: aborting due to previous error
10+
11+
For more information about this error, try `rustc --explain E0277`.

‎src/test/ui/associated-type-bounds/duplicate.rs

+94-71
Large diffs are not rendered by default.

‎src/test/ui/associated-type-bounds/duplicate.stderr

+148-76
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,33 @@
11
// compile-fail
2-
// ignore-tidy-linelength
3-
// error-pattern:could not find defining uses
4-
52
#![feature(associated_type_bounds)]
63
#![feature(untagged_unions)]
74

85
struct S1 { f: dyn Iterator<Item: Copy> }
9-
//~^ associated type bounds are not allowed within structs, enums, or unions
10-
//~| the value of the associated type `Item` (from the trait `std::iter::Iterator`) must be specified [E0191]
6+
//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
7+
//~| ERROR could not find defining uses
118
struct S2 { f: Box<dyn Iterator<Item: Copy>> }
12-
//~^ associated type bounds are not allowed within structs, enums, or unions
13-
//~| the value of the associated type `Item` (from the trait `std::iter::Iterator`) must be specified [E0191]
9+
//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
10+
//~| ERROR could not find defining uses
1411
struct S3 { f: dyn Iterator<Item: 'static> }
15-
//~^ associated type bounds are not allowed within structs, enums, or unions
16-
//~| the value of the associated type `Item` (from the trait `std::iter::Iterator`) must be specified [E0191]
12+
//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
13+
//~| ERROR could not find defining uses
1714

1815
enum E1 { V(dyn Iterator<Item: Copy>) }
19-
//~^ associated type bounds are not allowed within structs, enums, or unions
20-
//~| the value of the associated type `Item` (from the trait `std::iter::Iterator`) must be specified [E0191]
16+
//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
17+
//~| ERROR could not find defining uses
2118
enum E2 { V(Box<dyn Iterator<Item: Copy>>) }
22-
//~^ associated type bounds are not allowed within structs, enums, or unions
23-
//~| the value of the associated type `Item` (from the trait `std::iter::Iterator`) must be specified [E0191]
19+
//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
20+
//~| ERROR could not find defining uses
2421
enum E3 { V(dyn Iterator<Item: 'static>) }
25-
//~^ associated type bounds are not allowed within structs, enums, or unions
26-
//~| the value of the associated type `Item` (from the trait `std::iter::Iterator`) must be specified [E0191]
22+
//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
23+
//~| ERROR could not find defining uses
2724

2825
union U1 { f: dyn Iterator<Item: Copy> }
29-
//~^ associated type bounds are not allowed within structs, enums, or unions
30-
//~| the value of the associated type `Item` (from the trait `std::iter::Iterator`) must be specified [E0191]
26+
//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
27+
//~| ERROR could not find defining uses
3128
union U2 { f: Box<dyn Iterator<Item: Copy>> }
32-
//~^ associated type bounds are not allowed within structs, enums, or unions
33-
//~| the value of the associated type `Item` (from the trait `std::iter::Iterator`) must be specified [E0191]
29+
//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
30+
//~| ERROR could not find defining uses
3431
union U3 { f: dyn Iterator<Item: 'static> }
35-
//~^ associated type bounds are not allowed within structs, enums, or unions
36-
//~| the value of the associated type `Item` (from the trait `std::iter::Iterator`) must be specified [E0191]
32+
//~^ ERROR associated type bounds are not allowed within structs, enums, or unions
33+
//~| ERROR could not find defining uses

‎src/test/ui/associated-type-bounds/inside-adt.stderr

+45-9
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,53 @@
11
error: associated type bounds are not allowed within structs, enums, or unions
2-
--> $DIR/inside-adt.rs:8:29
2+
--> $DIR/inside-adt.rs:5:29
33
|
44
LL | struct S1 { f: dyn Iterator<Item: Copy> }
55
| ^^^^^^^^^^
66

77
error: associated type bounds are not allowed within structs, enums, or unions
8-
--> $DIR/inside-adt.rs:11:33
8+
--> $DIR/inside-adt.rs:8:33
99
|
1010
LL | struct S2 { f: Box<dyn Iterator<Item: Copy>> }
1111
| ^^^^^^^^^^
1212

1313
error: associated type bounds are not allowed within structs, enums, or unions
14-
--> $DIR/inside-adt.rs:14:29
14+
--> $DIR/inside-adt.rs:11:29
1515
|
1616
LL | struct S3 { f: dyn Iterator<Item: 'static> }
1717
| ^^^^^^^^^^^^^
1818

1919
error: associated type bounds are not allowed within structs, enums, or unions
20-
--> $DIR/inside-adt.rs:18:26
20+
--> $DIR/inside-adt.rs:15:26
2121
|
2222
LL | enum E1 { V(dyn Iterator<Item: Copy>) }
2323
| ^^^^^^^^^^
2424

2525
error: associated type bounds are not allowed within structs, enums, or unions
26-
--> $DIR/inside-adt.rs:21:30
26+
--> $DIR/inside-adt.rs:18:30
2727
|
2828
LL | enum E2 { V(Box<dyn Iterator<Item: Copy>>) }
2929
| ^^^^^^^^^^
3030

3131
error: associated type bounds are not allowed within structs, enums, or unions
32-
--> $DIR/inside-adt.rs:24:26
32+
--> $DIR/inside-adt.rs:21:26
3333
|
3434
LL | enum E3 { V(dyn Iterator<Item: 'static>) }
3535
| ^^^^^^^^^^^^^
3636

3737
error: associated type bounds are not allowed within structs, enums, or unions
38-
--> $DIR/inside-adt.rs:28:28
38+
--> $DIR/inside-adt.rs:25:28
3939
|
4040
LL | union U1 { f: dyn Iterator<Item: Copy> }
4141
| ^^^^^^^^^^
4242

4343
error: associated type bounds are not allowed within structs, enums, or unions
44-
--> $DIR/inside-adt.rs:31:32
44+
--> $DIR/inside-adt.rs:28:32
4545
|
4646
LL | union U2 { f: Box<dyn Iterator<Item: Copy>> }
4747
| ^^^^^^^^^^
4848

4949
error: associated type bounds are not allowed within structs, enums, or unions
50-
--> $DIR/inside-adt.rs:34:28
50+
--> $DIR/inside-adt.rs:31:28
5151
|
5252
LL | union U3 { f: dyn Iterator<Item: 'static> }
5353
| ^^^^^^^^^^^^^
@@ -57,22 +57,58 @@ error[E0601]: `main` function not found in crate `inside_adt`
5757
= note: consider adding a `main` function to `$DIR/inside-adt.rs`
5858

5959
error: could not find defining uses
60+
--> $DIR/inside-adt.rs:5:29
61+
|
62+
LL | struct S1 { f: dyn Iterator<Item: Copy> }
63+
| ^^^^^^^^^^
6064

6165
error: could not find defining uses
66+
--> $DIR/inside-adt.rs:8:33
67+
|
68+
LL | struct S2 { f: Box<dyn Iterator<Item: Copy>> }
69+
| ^^^^^^^^^^
6270

6371
error: could not find defining uses
72+
--> $DIR/inside-adt.rs:11:29
73+
|
74+
LL | struct S3 { f: dyn Iterator<Item: 'static> }
75+
| ^^^^^^^^^^^^^
6476

6577
error: could not find defining uses
78+
--> $DIR/inside-adt.rs:15:26
79+
|
80+
LL | enum E1 { V(dyn Iterator<Item: Copy>) }
81+
| ^^^^^^^^^^
6682

6783
error: could not find defining uses
84+
--> $DIR/inside-adt.rs:18:30
85+
|
86+
LL | enum E2 { V(Box<dyn Iterator<Item: Copy>>) }
87+
| ^^^^^^^^^^
6888

6989
error: could not find defining uses
90+
--> $DIR/inside-adt.rs:21:26
91+
|
92+
LL | enum E3 { V(dyn Iterator<Item: 'static>) }
93+
| ^^^^^^^^^^^^^
7094

7195
error: could not find defining uses
96+
--> $DIR/inside-adt.rs:25:28
97+
|
98+
LL | union U1 { f: dyn Iterator<Item: Copy> }
99+
| ^^^^^^^^^^
72100

73101
error: could not find defining uses
102+
--> $DIR/inside-adt.rs:28:32
103+
|
104+
LL | union U2 { f: Box<dyn Iterator<Item: Copy>> }
105+
| ^^^^^^^^^^
74106

75107
error: could not find defining uses
108+
--> $DIR/inside-adt.rs:31:28
109+
|
110+
LL | union U3 { f: dyn Iterator<Item: 'static> }
111+
| ^^^^^^^^^^^^^
76112

77113
error: aborting due to 19 previous errors
78114

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// edition:2018
2+
#![feature(async_closure,async_await)]
3+
fn foo() -> Box<dyn std::future::Future<Output = u32>> {
4+
let x = 0u32;
5+
Box::new((async || x)())
6+
//~^ ERROR E0373
7+
}
8+
9+
fn main() {
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
2+
--> $DIR/async-borrowck-escaping-closure-error.rs:5:15
3+
|
4+
LL | Box::new((async || x)())
5+
| ^^^^^^^^ - `x` is borrowed here
6+
| |
7+
| may outlive borrowed value `x`
8+
|
9+
note: closure is returned here
10+
--> $DIR/async-borrowck-escaping-closure-error.rs:5:5
11+
|
12+
LL | Box::new((async || x)())
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^
14+
help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
15+
|
16+
LL | Box::new((async move || x)())
17+
| ^^^^^^^^^^^^^
18+
19+
error: aborting due to previous error
20+
21+
For more information about this error, try `rustc --explain E0373`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Regression test for #62517. We used to ICE when you had an `async
2+
// fn` with an `impl Trait` return that mentioned a `dyn Bar` with no
3+
// explicit lifetime bound.
4+
//
5+
// edition:2018
6+
// check-pass
7+
8+
#![feature(async_await)]
9+
10+
trait FirstTrait {}
11+
trait SecondTrait {
12+
type Item: ?Sized;
13+
}
14+
15+
async fn foo(x: &str) -> impl SecondTrait<Item = dyn FirstTrait> {
16+
}
17+
18+
19+
impl<T> SecondTrait for T {
20+
type Item = dyn FirstTrait;
21+
}
22+
23+
fn main() { }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Regression test for #62517. We used to ICE when you had an `async
2+
// fn` with an `impl Trait` return that mentioned a `dyn Bar` with no
3+
// explicit lifetime bound.
4+
//
5+
// edition:2018
6+
// check-pass
7+
8+
#![feature(async_await)]
9+
10+
trait Object {}
11+
12+
trait Alpha<Param: ?Sized> {}
13+
14+
async fn foo<'a>(_: &'a ()) -> impl Alpha<dyn Object> {}
15+
16+
impl<T> Alpha<dyn Object> for T { }
17+
18+
fn main() { }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Test that we don't get an error with `dyn Bar` in an impl Trait
2+
// when there are multiple inputs. The `dyn Bar` should default to `+
3+
// 'static`. This used to erroneously generate an error (cc #62517).
4+
//
5+
// check-pass
6+
7+
trait Foo { type Item: ?Sized; }
8+
trait Bar { }
9+
10+
impl<T> Foo for T {
11+
type Item = dyn Bar;
12+
}
13+
14+
fn foo(x: &str, y: &str) -> impl Foo<Item = dyn Bar> { () }
15+
16+
fn main() { }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Test that we don't get an error with `dyn Object` in an impl Trait
2+
// when there are multiple inputs. The `dyn Object` should default to `+
3+
// 'static`. This used to erroneously generate an error (cc #62517).
4+
//
5+
// check-pass
6+
7+
trait Alpha<Item: ?Sized> {}
8+
trait Object {}
9+
impl<T> Alpha<dyn Object> for T {}
10+
fn alpha(x: &str, y: &str) -> impl Alpha<dyn Object> { () }
11+
fn main() { }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Test that we don't get an error with `dyn Bar` in an impl Trait
2+
// when there are multiple inputs. The `dyn Bar` should default to `+
3+
// 'static`. This used to erroneously generate an error (cc #62517).
4+
//
5+
// check-pass
6+
7+
trait Foo {
8+
type Item: ?Sized;
9+
10+
fn item(&self) -> Box<Self::Item> { panic!() }
11+
}
12+
13+
trait Bar { }
14+
15+
impl<T> Foo for T {
16+
type Item = dyn Bar;
17+
}
18+
19+
fn is_static<T>(_: T) where T: 'static { }
20+
21+
fn bar(x: &str) -> &impl Foo<Item = dyn Bar> { &() }
22+
23+
fn main() {
24+
let s = format!("foo");
25+
let r = bar(&s);
26+
is_static(r.item());
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Test that `impl Alpha<dyn Object>` resets the object-lifetime
2+
// default to `'static`.
3+
//
4+
// check-pass
5+
6+
trait Alpha<Item: ?Sized> {
7+
fn item(&self) -> Box<Item> {
8+
panic!()
9+
}
10+
}
11+
12+
trait Object {}
13+
impl<T> Alpha<dyn Object> for T {}
14+
fn alpha(x: &str, y: &str) -> impl Alpha<dyn Object> { () }
15+
fn is_static<T>(_: T) where T: 'static { }
16+
17+
fn bar(x: &str) -> &impl Alpha<dyn Object> { &() }
18+
19+
fn main() {
20+
let s = format!("foo");
21+
let r = bar(&s);
22+
is_static(r.item());
23+
}

‎src/test/ui/lifetimes/lifetime-elision-return-type-trait.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ trait Future {
66
use std::error::Error;
77

88
fn foo() -> impl Future<Item=(), Error=Box<dyn Error>> {
9-
//~^ ERROR missing lifetime
9+
//~^ ERROR not satisfied
1010
Ok(())
1111
}
1212

Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
error[E0106]: missing lifetime specifier
2-
--> $DIR/lifetime-elision-return-type-trait.rs:8:44
1+
error[E0277]: the trait bound `std::result::Result<(), _>: Future` is not satisfied
2+
--> $DIR/lifetime-elision-return-type-trait.rs:8:13
33
|
44
LL | fn foo() -> impl Future<Item=(), Error=Box<dyn Error>> {
5-
| ^^^^^^^^^ help: consider giving it a 'static lifetime: `dyn Error + 'static`
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Future` is not implemented for `std::result::Result<(), _>`
66
|
7-
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
7+
= note: the return type of a function must have a statically known size
88

99
error: aborting due to previous error
1010

11-
For more information about this error, try `rustc --explain E0106`.
11+
For more information about this error, try `rustc --explain E0277`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Test that `dyn Bar<Item = XX>` uses `'static` as the default object
2+
// lifetime bound for the type `XX`.
3+
4+
trait Foo<'a> {
5+
type Item: ?Sized;
6+
7+
fn item(&self) -> Box<Self::Item> { panic!() }
8+
}
9+
10+
trait Bar { }
11+
12+
impl<T> Foo<'_> for T {
13+
type Item = dyn Bar;
14+
}
15+
16+
fn is_static<T>(_: T) where T: 'static { }
17+
18+
// Here, we should default to `dyn Bar + 'static`, but the current
19+
// code forces us into a conservative, hacky path.
20+
fn bar<'a>(x: &'a str) -> &'a dyn Foo<'a, Item = dyn Bar> { &() }
21+
//~^ ERROR please supply an explicit bound
22+
23+
fn main() {
24+
let s = format!("foo");
25+
let r = bar(&s);
26+
is_static(r.item());
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound
2+
--> $DIR/object-lifetime-default-dyn-binding-nonstatic1.rs:20:50
3+
|
4+
LL | fn bar<'a>(x: &'a str) -> &'a dyn Foo<'a, Item = dyn Bar> { &() }
5+
| ^^^^^^^
6+
7+
error: aborting due to previous error
8+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Test that `dyn Bar<Item = XX>` uses `'static` as the default object
2+
// lifetime bound for the type `XX`.
3+
4+
trait Foo<'a> {
5+
type Item: 'a + ?Sized;
6+
7+
fn item(&self) -> Box<Self::Item> { panic!() }
8+
}
9+
10+
trait Bar { }
11+
12+
impl<T> Foo<'_> for T {
13+
type Item = dyn Bar;
14+
}
15+
16+
fn is_static<T>(_: T) where T: 'static { }
17+
18+
// Here, we default to `dyn Bar + 'a`. Or, we *should*, but the
19+
// current code forces us into a conservative, hacky path.
20+
fn bar<'a>(x: &'a str) -> &'a dyn Foo<'a, Item = dyn Bar> { &() }
21+
//~^ ERROR please supply an explicit bound
22+
23+
fn main() {
24+
let s = format!("foo");
25+
let r = bar(&s);
26+
27+
// If it weren't for the conservative path above, we'd expect an
28+
// error here.
29+
is_static(r.item());
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound
2+
--> $DIR/object-lifetime-default-dyn-binding-nonstatic2.rs:20:50
3+
|
4+
LL | fn bar<'a>(x: &'a str) -> &'a dyn Foo<'a, Item = dyn Bar> { &() }
5+
| ^^^^^^^
6+
7+
error: aborting due to previous error
8+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Test that `dyn Bar<Item = XX>` uses `'static` as the default object
2+
// lifetime bound for the type `XX`.
3+
4+
trait Foo<'a> {
5+
type Item: ?Sized;
6+
7+
fn item(&self) -> Box<Self::Item> { panic!() }
8+
}
9+
10+
trait Bar { }
11+
12+
fn is_static<T>(_: T) where T: 'static { }
13+
14+
// Here, we should default to `dyn Bar + 'static`, but the current
15+
// code forces us into a conservative, hacky path.
16+
fn bar(x: &str) -> &dyn Foo<Item = dyn Bar> { &() }
17+
//~^ ERROR please supply an explicit bound
18+
19+
fn main() {
20+
let s = format!("foo");
21+
let r = bar(&s);
22+
is_static(r.item());
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error[E0228]: the lifetime bound for this object type cannot be deduced from context; please supply an explicit bound
2+
--> $DIR/object-lifetime-default-dyn-binding-nonstatic3.rs:16:36
3+
|
4+
LL | fn bar(x: &str) -> &dyn Foo<Item = dyn Bar> { &() }
5+
| ^^^^^^^
6+
7+
error: aborting due to previous error
8+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Test that `dyn Bar<Item = XX>` uses `'static` as the default object
2+
// lifetime bound for the type `XX`.
3+
//
4+
// check-pass
5+
6+
trait Foo {
7+
type Item: ?Sized;
8+
9+
fn item(&self) -> Box<Self::Item> { panic!() }
10+
}
11+
12+
trait Bar { }
13+
14+
impl<T> Foo for T {
15+
type Item = dyn Bar;
16+
}
17+
18+
fn is_static<T>(_: T) where T: 'static { }
19+
20+
// Here, we default to `dyn Bar + 'static`, and not `&'x dyn Foo<Item
21+
// = dyn Bar + 'x>`.
22+
fn bar(x: &str) -> &dyn Foo<Item = dyn Bar> { &() }
23+
24+
fn main() {
25+
let s = format!("foo");
26+
let r = bar(&s);
27+
is_static(r.item());
28+
}

0 commit comments

Comments
 (0)
Please sign in to comment.