Skip to content

Commit f6d829a

Browse files
authored
Rollup merge of rust-lang#73783 - estebank:impl-dyn-trait-static-lifetime, r=nikomatsakis
Detect when `'static` obligation might come from an `impl` Partly address rust-lang#71341.
2 parents 7c29736 + 5136013 commit f6d829a

File tree

57 files changed

+996
-439
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+996
-439
lines changed

src/librustc_error_codes/error_codes.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -632,4 +632,5 @@ E0770: include_str!("./error_codes/E0770.md"),
632632
E0755, // `#[ffi_pure]` is only allowed on foreign functions
633633
E0756, // `#[ffi_const]` is only allowed on foreign functions
634634
E0757, // `#[ffi_const]` functions cannot be `#[ffi_pure]`
635+
E0767, // `'static' obligation coming from `impl dyn Trait {}` or `impl Foo for dyn Bar {}`.
635636
}

src/librustc_hir/hir.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2198,7 +2198,17 @@ pub enum IsAsync {
21982198
NotAsync,
21992199
}
22002200

2201-
#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
2201+
#[derive(
2202+
Copy,
2203+
Clone,
2204+
PartialEq,
2205+
RustcEncodable,
2206+
RustcDecodable,
2207+
Debug,
2208+
HashStable_Generic,
2209+
Eq,
2210+
Hash
2211+
)]
22022212
pub enum Defaultness {
22032213
Default { has_value: bool },
22042214
Final,

src/librustc_infer/infer/combine.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,13 @@ use crate::traits::{Obligation, PredicateObligations};
3636

3737
use rustc_ast::ast;
3838
use rustc_hir::def_id::DefId;
39+
use rustc_middle::traits::ObligationCause;
3940
use rustc_middle::ty::error::TypeError;
4041
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
4142
use rustc_middle::ty::subst::SubstsRef;
4243
use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeFoldable};
4344
use rustc_middle::ty::{IntType, UintType};
44-
use rustc_span::{Span, DUMMY_SP};
45+
use rustc_span::DUMMY_SP;
4546

4647
#[derive(Clone)]
4748
pub struct CombineFields<'infcx, 'tcx> {
@@ -367,10 +368,11 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
367368
};
368369

369370
debug!("generalize: for_universe = {:?}", for_universe);
371+
debug!("generalize: trace = {:?}", self.trace);
370372

371373
let mut generalize = Generalizer {
372374
infcx: self.infcx,
373-
span: self.trace.cause.span,
375+
cause: &self.trace.cause,
374376
for_vid_sub_root: self.infcx.inner.borrow_mut().type_variables().sub_root_var(for_vid),
375377
for_universe,
376378
ambient_variance,
@@ -414,7 +416,7 @@ struct Generalizer<'cx, 'tcx> {
414416
infcx: &'cx InferCtxt<'cx, 'tcx>,
415417

416418
/// The span, used when creating new type variables and things.
417-
span: Span,
419+
cause: &'cx ObligationCause<'tcx>,
418420

419421
/// The vid of the type variable that is in the process of being
420422
/// instantiated; if we find this within the type we are folding,
@@ -639,7 +641,7 @@ impl TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
639641

640642
// FIXME: This is non-ideal because we don't give a
641643
// very descriptive origin for this region variable.
642-
Ok(self.infcx.next_region_var_in_universe(MiscVariable(self.span), self.for_universe))
644+
Ok(self.infcx.next_region_var_in_universe(MiscVariable(self.cause.span), self.for_universe))
643645
}
644646

645647
fn consts(

src/librustc_infer/infer/error_reporting/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2007,7 +2007,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
20072007
infer::MiscVariable(_) => String::new(),
20082008
infer::PatternRegion(_) => " for pattern".to_string(),
20092009
infer::AddrOfRegion(_) => " for borrow expression".to_string(),
2010-
infer::Autoref(_) => " for autoref".to_string(),
2010+
infer::Autoref(_, _) => " for autoref".to_string(),
20112011
infer::Coercion(_) => " for automatic coercion".to_string(),
20122012
infer::LateBoundRegion(_, br, infer::FnCall) => {
20132013
format!(" for lifetime parameter {}in function call", br_string(br))

src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs

Lines changed: 454 additions & 197 deletions
Large diffs are not rendered by default.

src/librustc_infer/infer/error_reporting/nice_region_error/util.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,18 @@ use rustc_hir::def_id::LocalDefId;
77
use rustc_middle::ty::{self, DefIdTree, Region, Ty};
88
use rustc_span::Span;
99

10-
// The struct contains the information about the anonymous region
11-
// we are searching for.
10+
/// Information about the anonymous region we are searching for.
1211
#[derive(Debug)]
1312
pub(super) struct AnonymousParamInfo<'tcx> {
14-
// the parameter corresponding to the anonymous region
13+
/// The parameter corresponding to the anonymous region.
1514
pub param: &'tcx hir::Param<'tcx>,
16-
// the type corresponding to the anonymopus region parameter
15+
/// The type corresponding to the anonymous region parameter.
1716
pub param_ty: Ty<'tcx>,
18-
// the ty::BoundRegion corresponding to the anonymous region
17+
/// The ty::BoundRegion corresponding to the anonymous region.
1918
pub bound_region: ty::BoundRegion,
20-
// param_ty_span contains span of parameter type
19+
/// The `Span` of the parameter type.
2120
pub param_ty_span: Span,
22-
// corresponds to id the argument is the first parameter
23-
// in the declaration
21+
/// Signals that the argument is the first parameter in the declaration.
2422
pub is_first: bool,
2523
}
2624

src/librustc_infer/infer/mod.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,7 @@ pub enum RegionVariableOrigin {
463463
AddrOfRegion(Span),
464464

465465
/// Regions created as part of an autoref of a method receiver
466-
Autoref(Span),
466+
Autoref(Span, ty::AssocItem),
467467

468468
/// Regions created as part of an automatic coercion
469469
Coercion(Span),
@@ -1798,15 +1798,15 @@ impl<'tcx> SubregionOrigin<'tcx> {
17981798
impl RegionVariableOrigin {
17991799
pub fn span(&self) -> Span {
18001800
match *self {
1801-
MiscVariable(a) => a,
1802-
PatternRegion(a) => a,
1803-
AddrOfRegion(a) => a,
1804-
Autoref(a) => a,
1805-
Coercion(a) => a,
1806-
EarlyBoundRegion(a, ..) => a,
1807-
LateBoundRegion(a, ..) => a,
1801+
MiscVariable(a)
1802+
| PatternRegion(a)
1803+
| AddrOfRegion(a)
1804+
| Autoref(a, _)
1805+
| Coercion(a)
1806+
| EarlyBoundRegion(a, ..)
1807+
| LateBoundRegion(a, ..)
1808+
| UpvarRegion(_, a) => a,
18081809
BoundRegionInCoherence(_) => rustc_span::DUMMY_SP,
1809-
UpvarRegion(_, a) => a,
18101810
NLL(..) => bug!("NLL variable used with `span`"),
18111811
}
18121812
}

src/librustc_infer/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
//! This API is completely unstable and subject to change.
1414
1515
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
16+
#![feature(bindings_after_at)]
1617
#![feature(bool_to_option)]
1718
#![feature(box_patterns)]
1819
#![feature(box_syntax)]

src/librustc_middle/traits/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,13 @@ impl<'tcx> ObligationCause<'tcx> {
169169
}
170170
}
171171

172+
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
173+
pub struct UnifyReceiverContext<'tcx> {
174+
pub assoc_item: ty::AssocItem,
175+
pub param_env: ty::ParamEnv<'tcx>,
176+
pub substs: SubstsRef<'tcx>,
177+
}
178+
172179
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
173180
pub enum ObligationCauseCode<'tcx> {
174181
/// Not well classified or should be obvious from the span.
@@ -300,6 +307,8 @@ pub enum ObligationCauseCode<'tcx> {
300307
/// Method receiver
301308
MethodReceiver,
302309

310+
UnifyReceiver(Box<UnifyReceiverContext<'tcx>>),
311+
303312
/// `return` with no expression
304313
ReturnNoExpression,
305314

src/librustc_middle/traits/structural_impls.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,12 +213,26 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
213213
super::StartFunctionType => Some(super::StartFunctionType),
214214
super::IntrinsicType => Some(super::IntrinsicType),
215215
super::MethodReceiver => Some(super::MethodReceiver),
216+
super::UnifyReceiver(ref ctxt) => tcx.lift(ctxt).map(|ctxt| super::UnifyReceiver(ctxt)),
216217
super::BlockTailExpression(id) => Some(super::BlockTailExpression(id)),
217218
super::TrivialBound => Some(super::TrivialBound),
218219
}
219220
}
220221
}
221222

223+
impl<'a, 'tcx> Lift<'tcx> for traits::UnifyReceiverContext<'a> {
224+
type Lifted = traits::UnifyReceiverContext<'tcx>;
225+
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
226+
tcx.lift(&self.param_env).and_then(|param_env| {
227+
tcx.lift(&self.substs).map(|substs| traits::UnifyReceiverContext {
228+
assoc_item: self.assoc_item,
229+
param_env,
230+
substs,
231+
})
232+
})
233+
}
234+
}
235+
222236
impl<'a, 'tcx> Lift<'tcx> for traits::DerivedObligationCause<'a> {
223237
type Lifted = traits::DerivedObligationCause<'tcx>;
224238
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {

src/librustc_middle/ty/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ pub struct ResolverOutputs {
136136
pub extern_prelude: FxHashMap<Symbol, bool>,
137137
}
138138

139-
#[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable)]
139+
#[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable, Hash)]
140140
pub enum AssocItemContainer {
141141
TraitContainer(DefId),
142142
ImplContainer(DefId),
@@ -184,7 +184,7 @@ pub enum ImplPolarity {
184184
Reservation,
185185
}
186186

187-
#[derive(Copy, Clone, Debug, PartialEq, HashStable)]
187+
#[derive(Copy, Clone, Debug, PartialEq, HashStable, Eq, Hash)]
188188
pub struct AssocItem {
189189
pub def_id: DefId,
190190
#[stable_hasher(project(name))]
@@ -199,7 +199,7 @@ pub struct AssocItem {
199199
pub fn_has_self_parameter: bool,
200200
}
201201

202-
#[derive(Copy, Clone, PartialEq, Debug, HashStable)]
202+
#[derive(Copy, Clone, PartialEq, Debug, HashStable, Eq, Hash)]
203203
pub enum AssocKind {
204204
Const,
205205
Fn,
@@ -316,7 +316,7 @@ impl<'tcx> AssociatedItems<'tcx> {
316316
}
317317
}
318318

319-
#[derive(Clone, Debug, PartialEq, Eq, Copy, RustcEncodable, RustcDecodable, HashStable)]
319+
#[derive(Clone, Debug, PartialEq, Eq, Copy, RustcEncodable, RustcDecodable, HashStable, Hash)]
320320
pub enum Visibility {
321321
/// Visible everywhere (including in other crates).
322322
Public,

src/librustc_trait_selection/traits/codegen/mod.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use crate::infer::{InferCtxt, TyCtxtInferExt};
77
use crate::traits::{
88
FulfillmentContext, ImplSource, Obligation, ObligationCause, SelectionContext, TraitEngine,
9+
Unimplemented,
910
};
1011
use rustc_errors::ErrorReported;
1112
use rustc_middle::ty::fold::TypeFoldable;
@@ -58,6 +59,18 @@ pub fn codegen_fulfill_obligation<'tcx>(
5859
);
5960
return Err(ErrorReported);
6061
}
62+
Err(Unimplemented) => {
63+
// This can trigger when we probe for the source of a `'static` lifetime requirement
64+
// on a trait object: `impl Foo for dyn Trait {}` has an implicit `'static` bound.
65+
infcx.tcx.sess.delay_span_bug(
66+
rustc_span::DUMMY_SP,
67+
&format!(
68+
"Encountered error `Unimplemented` selecting `{:?}` during codegen",
69+
trait_ref
70+
),
71+
);
72+
return Err(ErrorReported);
73+
}
6174
Err(e) => {
6275
bug!("Encountered error `{:?}` selecting `{:?}` during codegen", e, trait_ref)
6376
}

src/librustc_trait_selection/traits/error_reporting/suggestions.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1706,6 +1706,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
17061706
| ObligationCauseCode::IntrinsicType
17071707
| ObligationCauseCode::MethodReceiver
17081708
| ObligationCauseCode::ReturnNoExpression
1709+
| ObligationCauseCode::UnifyReceiver(..)
17091710
| ObligationCauseCode::MiscObligation => {}
17101711
ObligationCauseCode::SliceOrArrayElem => {
17111712
err.note("slice and array elements must have `Sized` type");

src/librustc_typeck/check/method/confirm.rs

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use crate::hir::def_id::DefId;
66
use crate::hir::GenericArg;
77
use rustc_hir as hir;
88
use rustc_infer::infer::{self, InferOk};
9+
use rustc_middle::traits::{ObligationCauseCode, UnifyReceiverContext};
910
use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast};
1011
use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
1112
use rustc_middle::ty::fold::TypeFoldable;
@@ -91,7 +92,11 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
9192
// signature (which is also done during probing).
9293
let method_sig_rcvr =
9394
self.normalize_associated_types_in(self.span, &method_sig.inputs()[0]);
94-
self.unify_receivers(self_ty, method_sig_rcvr);
95+
debug!(
96+
"confirm: self_ty={:?} method_sig_rcvr={:?} method_sig={:?} method_predicates={:?}",
97+
self_ty, method_sig_rcvr, method_sig, method_predicates
98+
);
99+
self.unify_receivers(self_ty, method_sig_rcvr, &pick, all_substs);
95100

96101
let (method_sig, method_predicates) =
97102
self.normalize_associated_types_in(self.span, &(method_sig, method_predicates));
@@ -150,7 +155,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
150155
self.structurally_resolved_type(autoderef.span(), autoderef.final_ty(false));
151156

152157
if let Some(mutbl) = pick.autoref {
153-
let region = self.next_region_var(infer::Autoref(self.span));
158+
let region = self.next_region_var(infer::Autoref(self.span, pick.item));
154159
target = self.tcx.mk_ref(region, ty::TypeAndMut { mutbl, ty: target });
155160
let mutbl = match mutbl {
156161
hir::Mutability::Not => AutoBorrowMutability::Not,
@@ -334,8 +339,26 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
334339
)
335340
}
336341

337-
fn unify_receivers(&mut self, self_ty: Ty<'tcx>, method_self_ty: Ty<'tcx>) {
338-
match self.at(&self.misc(self.span), self.param_env).sup(method_self_ty, self_ty) {
342+
fn unify_receivers(
343+
&mut self,
344+
self_ty: Ty<'tcx>,
345+
method_self_ty: Ty<'tcx>,
346+
pick: &probe::Pick<'tcx>,
347+
substs: SubstsRef<'tcx>,
348+
) {
349+
debug!(
350+
"unify_receivers: self_ty={:?} method_self_ty={:?} span={:?} pick={:?}",
351+
self_ty, method_self_ty, self.span, pick
352+
);
353+
let cause = self.cause(
354+
self.span,
355+
ObligationCauseCode::UnifyReceiver(Box::new(UnifyReceiverContext {
356+
assoc_item: pick.item,
357+
param_env: self.param_env,
358+
substs,
359+
})),
360+
);
361+
match self.at(&cause, self.param_env).sup(method_self_ty, self_ty) {
339362
Ok(InferOk { obligations, value: () }) => {
340363
self.register_predicates(obligations);
341364
}

src/test/ui/associated-types/cache/project-fn-ret-contravariant.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ fn baz<'a,'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) {
3535

3636
#[cfg(transmute)] // one instantiations: BAD
3737
fn baz<'a,'b>(x: &'a u32) -> &'static u32 {
38-
bar(foo, x) //[transmute]~ ERROR E0495
38+
bar(foo, x) //[transmute]~ ERROR E0759
3939
}
4040

4141
#[cfg(krisskross)] // two instantiations, mixing and matching: BAD
Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,11 @@
1-
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
1+
error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
22
--> $DIR/project-fn-ret-contravariant.rs:38:8
33
|
4-
LL | bar(foo, x)
5-
| ^^^
6-
|
7-
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 37:8...
8-
--> $DIR/project-fn-ret-contravariant.rs:37:8
9-
|
104
LL | fn baz<'a,'b>(x: &'a u32) -> &'static u32 {
11-
| ^^
12-
note: ...so that reference does not outlive borrowed content
13-
--> $DIR/project-fn-ret-contravariant.rs:38:13
14-
|
15-
LL | bar(foo, x)
16-
| ^
17-
= note: but, the lifetime must be valid for the static lifetime...
18-
note: ...so that reference does not outlive borrowed content
19-
--> $DIR/project-fn-ret-contravariant.rs:38:4
20-
|
5+
| ------- this data with lifetime `'a`...
216
LL | bar(foo, x)
22-
| ^^^^^^^^^^^
7+
| ----^^^---- ...is captured and required to live as long as `'static` here
238

249
error: aborting due to previous error
2510

26-
For more information about this error, try `rustc --explain E0495`.
11+
For more information about this error, try `rustc --explain E0759`.

src/test/ui/associated-types/cache/project-fn-ret-invariant.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> {
4646
// Cannot instantiate `foo` with any lifetime other than `'a`,
4747
// since it is provided as input.
4848

49-
bar(foo, x) //[transmute]~ ERROR E0495
49+
bar(foo, x) //[transmute]~ ERROR E0759
5050
}
5151

5252
#[cfg(krisskross)] // two instantiations, mixing and matching: BAD

0 commit comments

Comments
 (0)