Skip to content

Commit

Permalink
Rollup merge of rust-lang#73783 - estebank:impl-dyn-trait-static-life…
Browse files Browse the repository at this point in the history
…time, r=nikomatsakis

Detect when `'static` obligation might come from an `impl`

Partly address rust-lang#71341.
  • Loading branch information
Manishearth authored Jul 17, 2020
2 parents 7c29736 + 5136013 commit f6d829a
Show file tree
Hide file tree
Showing 57 changed files with 996 additions and 439 deletions.
1 change: 1 addition & 0 deletions src/librustc_error_codes/error_codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -632,4 +632,5 @@ E0770: include_str!("./error_codes/E0770.md"),
E0755, // `#[ffi_pure]` is only allowed on foreign functions
E0756, // `#[ffi_const]` is only allowed on foreign functions
E0757, // `#[ffi_const]` functions cannot be `#[ffi_pure]`
E0767, // `'static' obligation coming from `impl dyn Trait {}` or `impl Foo for dyn Bar {}`.
}
12 changes: 11 additions & 1 deletion src/librustc_hir/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2198,7 +2198,17 @@ pub enum IsAsync {
NotAsync,
}

#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
#[derive(
Copy,
Clone,
PartialEq,
RustcEncodable,
RustcDecodable,
Debug,
HashStable_Generic,
Eq,
Hash
)]
pub enum Defaultness {
Default { has_value: bool },
Final,
Expand Down
10 changes: 6 additions & 4 deletions src/librustc_infer/infer/combine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,13 @@ use crate::traits::{Obligation, PredicateObligations};

use rustc_ast::ast;
use rustc_hir::def_id::DefId;
use rustc_middle::traits::ObligationCause;
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::relate::{self, Relate, RelateResult, TypeRelation};
use rustc_middle::ty::subst::SubstsRef;
use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeFoldable};
use rustc_middle::ty::{IntType, UintType};
use rustc_span::{Span, DUMMY_SP};
use rustc_span::DUMMY_SP;

#[derive(Clone)]
pub struct CombineFields<'infcx, 'tcx> {
Expand Down Expand Up @@ -367,10 +368,11 @@ impl<'infcx, 'tcx> CombineFields<'infcx, 'tcx> {
};

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

let mut generalize = Generalizer {
infcx: self.infcx,
span: self.trace.cause.span,
cause: &self.trace.cause,
for_vid_sub_root: self.infcx.inner.borrow_mut().type_variables().sub_root_var(for_vid),
for_universe,
ambient_variance,
Expand Down Expand Up @@ -414,7 +416,7 @@ struct Generalizer<'cx, 'tcx> {
infcx: &'cx InferCtxt<'cx, 'tcx>,

/// The span, used when creating new type variables and things.
span: Span,
cause: &'cx ObligationCause<'tcx>,

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

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

fn consts(
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_infer/infer/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2007,7 +2007,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
infer::MiscVariable(_) => String::new(),
infer::PatternRegion(_) => " for pattern".to_string(),
infer::AddrOfRegion(_) => " for borrow expression".to_string(),
infer::Autoref(_) => " for autoref".to_string(),
infer::Autoref(_, _) => " for autoref".to_string(),
infer::Coercion(_) => " for automatic coercion".to_string(),
infer::LateBoundRegion(_, br, infer::FnCall) => {
format!(" for lifetime parameter {}in function call", br_string(br))
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,18 @@ use rustc_hir::def_id::LocalDefId;
use rustc_middle::ty::{self, DefIdTree, Region, Ty};
use rustc_span::Span;

// The struct contains the information about the anonymous region
// we are searching for.
/// Information about the anonymous region we are searching for.
#[derive(Debug)]
pub(super) struct AnonymousParamInfo<'tcx> {
// the parameter corresponding to the anonymous region
/// The parameter corresponding to the anonymous region.
pub param: &'tcx hir::Param<'tcx>,
// the type corresponding to the anonymopus region parameter
/// The type corresponding to the anonymous region parameter.
pub param_ty: Ty<'tcx>,
// the ty::BoundRegion corresponding to the anonymous region
/// The ty::BoundRegion corresponding to the anonymous region.
pub bound_region: ty::BoundRegion,
// param_ty_span contains span of parameter type
/// The `Span` of the parameter type.
pub param_ty_span: Span,
// corresponds to id the argument is the first parameter
// in the declaration
/// Signals that the argument is the first parameter in the declaration.
pub is_first: bool,
}

Expand Down
18 changes: 9 additions & 9 deletions src/librustc_infer/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@ pub enum RegionVariableOrigin {
AddrOfRegion(Span),

/// Regions created as part of an autoref of a method receiver
Autoref(Span),
Autoref(Span, ty::AssocItem),

/// Regions created as part of an automatic coercion
Coercion(Span),
Expand Down Expand Up @@ -1798,15 +1798,15 @@ impl<'tcx> SubregionOrigin<'tcx> {
impl RegionVariableOrigin {
pub fn span(&self) -> Span {
match *self {
MiscVariable(a) => a,
PatternRegion(a) => a,
AddrOfRegion(a) => a,
Autoref(a) => a,
Coercion(a) => a,
EarlyBoundRegion(a, ..) => a,
LateBoundRegion(a, ..) => a,
MiscVariable(a)
| PatternRegion(a)
| AddrOfRegion(a)
| Autoref(a, _)
| Coercion(a)
| EarlyBoundRegion(a, ..)
| LateBoundRegion(a, ..)
| UpvarRegion(_, a) => a,
BoundRegionInCoherence(_) => rustc_span::DUMMY_SP,
UpvarRegion(_, a) => a,
NLL(..) => bug!("NLL variable used with `span`"),
}
}
Expand Down
1 change: 1 addition & 0 deletions src/librustc_infer/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
//! This API is completely unstable and subject to change.
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
#![feature(bindings_after_at)]
#![feature(bool_to_option)]
#![feature(box_patterns)]
#![feature(box_syntax)]
Expand Down
9 changes: 9 additions & 0 deletions src/librustc_middle/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,13 @@ impl<'tcx> ObligationCause<'tcx> {
}
}

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct UnifyReceiverContext<'tcx> {
pub assoc_item: ty::AssocItem,
pub param_env: ty::ParamEnv<'tcx>,
pub substs: SubstsRef<'tcx>,
}

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum ObligationCauseCode<'tcx> {
/// Not well classified or should be obvious from the span.
Expand Down Expand Up @@ -300,6 +307,8 @@ pub enum ObligationCauseCode<'tcx> {
/// Method receiver
MethodReceiver,

UnifyReceiver(Box<UnifyReceiverContext<'tcx>>),

/// `return` with no expression
ReturnNoExpression,

Expand Down
14 changes: 14 additions & 0 deletions src/librustc_middle/traits/structural_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,12 +213,26 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
super::StartFunctionType => Some(super::StartFunctionType),
super::IntrinsicType => Some(super::IntrinsicType),
super::MethodReceiver => Some(super::MethodReceiver),
super::UnifyReceiver(ref ctxt) => tcx.lift(ctxt).map(|ctxt| super::UnifyReceiver(ctxt)),
super::BlockTailExpression(id) => Some(super::BlockTailExpression(id)),
super::TrivialBound => Some(super::TrivialBound),
}
}
}

impl<'a, 'tcx> Lift<'tcx> for traits::UnifyReceiverContext<'a> {
type Lifted = traits::UnifyReceiverContext<'tcx>;
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
tcx.lift(&self.param_env).and_then(|param_env| {
tcx.lift(&self.substs).map(|substs| traits::UnifyReceiverContext {
assoc_item: self.assoc_item,
param_env,
substs,
})
})
}
}

impl<'a, 'tcx> Lift<'tcx> for traits::DerivedObligationCause<'a> {
type Lifted = traits::DerivedObligationCause<'tcx>;
fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
Expand Down
8 changes: 4 additions & 4 deletions src/librustc_middle/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ pub struct ResolverOutputs {
pub extern_prelude: FxHashMap<Symbol, bool>,
}

#[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable)]
#[derive(Clone, Copy, PartialEq, Eq, Debug, HashStable, Hash)]
pub enum AssocItemContainer {
TraitContainer(DefId),
ImplContainer(DefId),
Expand Down Expand Up @@ -184,7 +184,7 @@ pub enum ImplPolarity {
Reservation,
}

#[derive(Copy, Clone, Debug, PartialEq, HashStable)]
#[derive(Copy, Clone, Debug, PartialEq, HashStable, Eq, Hash)]
pub struct AssocItem {
pub def_id: DefId,
#[stable_hasher(project(name))]
Expand All @@ -199,7 +199,7 @@ pub struct AssocItem {
pub fn_has_self_parameter: bool,
}

#[derive(Copy, Clone, PartialEq, Debug, HashStable)]
#[derive(Copy, Clone, PartialEq, Debug, HashStable, Eq, Hash)]
pub enum AssocKind {
Const,
Fn,
Expand Down Expand Up @@ -316,7 +316,7 @@ impl<'tcx> AssociatedItems<'tcx> {
}
}

#[derive(Clone, Debug, PartialEq, Eq, Copy, RustcEncodable, RustcDecodable, HashStable)]
#[derive(Clone, Debug, PartialEq, Eq, Copy, RustcEncodable, RustcDecodable, HashStable, Hash)]
pub enum Visibility {
/// Visible everywhere (including in other crates).
Public,
Expand Down
13 changes: 13 additions & 0 deletions src/librustc_trait_selection/traits/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use crate::infer::{InferCtxt, TyCtxtInferExt};
use crate::traits::{
FulfillmentContext, ImplSource, Obligation, ObligationCause, SelectionContext, TraitEngine,
Unimplemented,
};
use rustc_errors::ErrorReported;
use rustc_middle::ty::fold::TypeFoldable;
Expand Down Expand Up @@ -58,6 +59,18 @@ pub fn codegen_fulfill_obligation<'tcx>(
);
return Err(ErrorReported);
}
Err(Unimplemented) => {
// This can trigger when we probe for the source of a `'static` lifetime requirement
// on a trait object: `impl Foo for dyn Trait {}` has an implicit `'static` bound.
infcx.tcx.sess.delay_span_bug(
rustc_span::DUMMY_SP,
&format!(
"Encountered error `Unimplemented` selecting `{:?}` during codegen",
trait_ref
),
);
return Err(ErrorReported);
}
Err(e) => {
bug!("Encountered error `{:?}` selecting `{:?}` during codegen", e, trait_ref)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1706,6 +1706,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
| ObligationCauseCode::IntrinsicType
| ObligationCauseCode::MethodReceiver
| ObligationCauseCode::ReturnNoExpression
| ObligationCauseCode::UnifyReceiver(..)
| ObligationCauseCode::MiscObligation => {}
ObligationCauseCode::SliceOrArrayElem => {
err.note("slice and array elements must have `Sized` type");
Expand Down
31 changes: 27 additions & 4 deletions src/librustc_typeck/check/method/confirm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::hir::def_id::DefId;
use crate::hir::GenericArg;
use rustc_hir as hir;
use rustc_infer::infer::{self, InferOk};
use rustc_middle::traits::{ObligationCauseCode, UnifyReceiverContext};
use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast};
use rustc_middle::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability};
use rustc_middle::ty::fold::TypeFoldable;
Expand Down Expand Up @@ -91,7 +92,11 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
// signature (which is also done during probing).
let method_sig_rcvr =
self.normalize_associated_types_in(self.span, &method_sig.inputs()[0]);
self.unify_receivers(self_ty, method_sig_rcvr);
debug!(
"confirm: self_ty={:?} method_sig_rcvr={:?} method_sig={:?} method_predicates={:?}",
self_ty, method_sig_rcvr, method_sig, method_predicates
);
self.unify_receivers(self_ty, method_sig_rcvr, &pick, all_substs);

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

if let Some(mutbl) = pick.autoref {
let region = self.next_region_var(infer::Autoref(self.span));
let region = self.next_region_var(infer::Autoref(self.span, pick.item));
target = self.tcx.mk_ref(region, ty::TypeAndMut { mutbl, ty: target });
let mutbl = match mutbl {
hir::Mutability::Not => AutoBorrowMutability::Not,
Expand Down Expand Up @@ -334,8 +339,26 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
)
}

fn unify_receivers(&mut self, self_ty: Ty<'tcx>, method_self_ty: Ty<'tcx>) {
match self.at(&self.misc(self.span), self.param_env).sup(method_self_ty, self_ty) {
fn unify_receivers(
&mut self,
self_ty: Ty<'tcx>,
method_self_ty: Ty<'tcx>,
pick: &probe::Pick<'tcx>,
substs: SubstsRef<'tcx>,
) {
debug!(
"unify_receivers: self_ty={:?} method_self_ty={:?} span={:?} pick={:?}",
self_ty, method_self_ty, self.span, pick
);
let cause = self.cause(
self.span,
ObligationCauseCode::UnifyReceiver(Box::new(UnifyReceiverContext {
assoc_item: pick.item,
param_env: self.param_env,
substs,
})),
);
match self.at(&cause, self.param_env).sup(method_self_ty, self_ty) {
Ok(InferOk { obligations, value: () }) => {
self.register_predicates(obligations);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ fn baz<'a,'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) {

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

#[cfg(krisskross)] // two instantiations, mixing and matching: BAD
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,11 @@
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
error[E0759]: `x` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
--> $DIR/project-fn-ret-contravariant.rs:38:8
|
LL | bar(foo, x)
| ^^^
|
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 37:8...
--> $DIR/project-fn-ret-contravariant.rs:37:8
|
LL | fn baz<'a,'b>(x: &'a u32) -> &'static u32 {
| ^^
note: ...so that reference does not outlive borrowed content
--> $DIR/project-fn-ret-contravariant.rs:38:13
|
LL | bar(foo, x)
| ^
= note: but, the lifetime must be valid for the static lifetime...
note: ...so that reference does not outlive borrowed content
--> $DIR/project-fn-ret-contravariant.rs:38:4
|
| ------- this data with lifetime `'a`...
LL | bar(foo, x)
| ^^^^^^^^^^^
| ----^^^---- ...is captured and required to live as long as `'static` here

error: aborting due to previous error

For more information about this error, try `rustc --explain E0495`.
For more information about this error, try `rustc --explain E0759`.
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ fn baz<'a, 'b>(x: Type<'a>) -> Type<'static> {
// Cannot instantiate `foo` with any lifetime other than `'a`,
// since it is provided as input.

bar(foo, x) //[transmute]~ ERROR E0495
bar(foo, x) //[transmute]~ ERROR E0759
}

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

0 comments on commit f6d829a

Please sign in to comment.