use borrow_check::nll::type_check::free_region_relations::{
CreateResult, UniversalRegionRelations,
};
-use borrow_check::nll::universal_regions::UniversalRegions;
+use borrow_check::nll::universal_regions::{DefiningTy, UniversalRegions};
use borrow_check::nll::ToRegionVid;
use dataflow::move_paths::MoveData;
use dataflow::FlowAtLocation;
use rustc::traits::query::{Fallible, NoSolution};
use rustc::traits::{ObligationCause, PredicateObligations};
use rustc::ty::fold::TypeFoldable;
-use rustc::ty::subst::{Subst, UnpackedKind};
-use rustc::ty::{self, CanonicalTy, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind};
+use rustc::ty::subst::{Subst, Substs, UnpackedKind};
+use rustc::ty::{self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind};
use std::rc::Rc;
use std::{fmt, iter};
use syntax_pos::{Span, DUMMY_SP};
let mut constraints = MirTypeckRegionConstraints {
liveness_constraints: LivenessValues::new(elements),
outlives_constraints: ConstraintSet::default(),
- closure_bounds_mapping: FxHashMap(),
+ closure_bounds_mapping: Default::default(),
type_tests: Vec::default(),
};
let mut placeholder_indices = PlaceholderIndices::default();
crate outlives_constraints: ConstraintSet,
- crate closure_bounds_mapping: FxHashMap<
- Location,
- FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>,
- >,
+ crate closure_bounds_mapping:
+ FxHashMap<Location, FxHashMap<(RegionVid, RegionVid), (ConstraintCategory, Span)>>,
crate type_tests: Vec<TypeTest<'tcx>>,
}
region_bound_pairs,
implicit_region_bound,
borrowck_context,
- reported_errors: FxHashSet(),
+ reported_errors: Default::default(),
universal_region_relations,
}
}
&mut self,
locations: Locations,
category: ConstraintCategory,
- op: impl type_op::TypeOp<'gcx, 'tcx, Output=R>,
+ op: impl type_op::TypeOp<'gcx, 'tcx, Output = R>,
) -> Fallible<R> {
let (r, opt_data) = op.fully_perform(self.infcx)?;
}
}
- fn sub_types(
+ /// Convenient wrapper around `relate_tys::relate_types` -- see
+ /// that fn for docs.
+ fn relate_types(
&mut self,
- sub: Ty<'tcx>,
- sup: Ty<'tcx>,
+ a: Ty<'tcx>,
+ v: ty::Variance,
+ b: Ty<'tcx>,
locations: Locations,
category: ConstraintCategory,
) -> Fallible<()> {
- relate_tys::sub_types(
+ relate_tys::relate_types(
self.infcx,
- sub,
- sup,
+ a,
+ v,
+ b,
locations,
category,
self.borrowck_context.as_mut().map(|x| &mut **x),
)
}
+ fn sub_types(
+ &mut self,
+ sub: Ty<'tcx>,
+ sup: Ty<'tcx>,
+ locations: Locations,
+ category: ConstraintCategory,
+ ) -> Fallible<()> {
+ self.relate_types(sub, ty::Variance::Covariant, sup, locations, category)
+ }
+
/// Try to relate `sub <: sup`; if this fails, instantiate opaque
/// variables in `sub` with their inferred definitions and try
/// again. This is used for opaque types in places (e.g., `let x:
locations: Locations,
category: ConstraintCategory,
) -> Fallible<()> {
- relate_tys::eq_types(
- self.infcx,
- a,
- b,
- locations,
- category,
- self.borrowck_context.as_mut().map(|x| &mut **x),
- )
+ self.relate_types(a, ty::Variance::Invariant, b, locations, category)
}
fn relate_type_and_user_type(
&mut self,
a: Ty<'tcx>,
v: ty::Variance,
- b: CanonicalTy<'tcx>,
+ user_ty: UserTypeAnnotation<'tcx>,
locations: Locations,
category: ConstraintCategory,
) -> Fallible<()> {
- let ty = relate_tys::relate_type_and_user_type(
- self.infcx,
- a,
- v,
- b,
- locations,
- category,
- self.borrowck_context.as_mut().map(|x| &mut **x),
- )?;
- self.prove_predicate(
- ty::Predicate::WellFormed(ty),
- locations,
- category,
+ debug!(
+ "relate_type_and_user_type(a={:?}, v={:?}, user_ty={:?}, locations={:?})",
+ a, v, user_ty, locations,
);
+
+ match user_ty {
+ UserTypeAnnotation::Ty(canonical_ty) => {
+ let (ty, _) = self.infcx
+ .instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &canonical_ty);
+
+ // The `TypeRelating` code assumes that "unresolved inference
+ // variables" appear in the "a" side, so flip `Contravariant`
+ // ambient variance to get the right relationship.
+ let v1 = ty::Contravariant.xform(v);
+
+ self.relate_types(ty, v1, a, locations, category)?;
+ }
+ UserTypeAnnotation::TypeOf(def_id, canonical_substs) => {
+ let (
+ user_substs,
+ _,
+ ) = self.infcx
+ .instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &canonical_substs);
+
+ self.fully_perform_op(
+ locations,
+ category,
+ self.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(
+ a, v, def_id, user_substs,
+ )),
+ )?;
+ }
+ }
+
Ok(())
}
// of lowering. Assignments to other sorts of places *are* interesting
// though.
let category = match *place {
- Place::Local(RETURN_PLACE) => ConstraintCategory::Return,
+ Place::Local(RETURN_PLACE) => if let Some(BorrowCheckContext {
+ universal_regions:
+ UniversalRegions {
+ defining_ty: DefiningTy::Const(def_id, _),
+ ..
+ },
+ ..
+ }) = self.borrowck_context
+ {
+ if tcx.is_static(*def_id).is_some() {
+ ConstraintCategory::UseAsStatic
+ } else {
+ ConstraintCategory::UseAsConst
+ }
+ } else {
+ ConstraintCategory::Return
+ },
Place::Local(l) if !mir.local_decls[l].is_user_variable.is_some() => {
ConstraintCategory::Boring
}
let place_ty = place.ty(mir, tcx).to_ty(tcx);
let rv_ty = rv.ty(mir, tcx);
if let Err(terr) =
- self.sub_types_or_anon(rv_ty, place_ty, location.to_locations(), category)
- {
- span_mirbug!(
+ self.sub_types_or_anon(rv_ty, place_ty, location.to_locations(), category)
+ {
+ span_mirbug!(
self,
stmt,
"bad assignment ({:?} = {:?}): {:?}",
rv_ty,
terr
);
- }
+ }
if let Some(user_ty) = self.rvalue_user_ty(rv) {
if let Err(terr) = self.relate_type_and_user_type(
let locations = term_location.to_locations();
if let Err(terr) =
- self.sub_types(rv_ty, place_ty, locations, ConstraintCategory::Assignment)
- {
- span_mirbug!(
+ self.sub_types(rv_ty, place_ty, locations, ConstraintCategory::Assignment)
+ {
+ span_mirbug!(
self,
term,
"bad DropAndReplace ({:?} = {:?}): {:?}",
rv_ty,
terr
);
- }
+ }
}
TerminatorKind::SwitchInt {
ref discr,
ref func,
ref args,
ref destination,
+ from_hir_call,
..
} => {
let func_ty = func.ty(mir, tcx);
}
}
- self.check_call_inputs(mir, term, &sig, args, term_location);
+ self.check_call_inputs(mir, term, &sig, args, term_location, from_hir_call);
}
TerminatorKind::Assert {
ref cond, ref msg, ..
Some((ref dest, _target_block)) => {
let dest_ty = dest.ty(mir, tcx).to_ty(tcx);
let category = match *dest {
- Place::Local(RETURN_PLACE) => ConstraintCategory::Return,
+ Place::Local(RETURN_PLACE) => {
+ if let Some(BorrowCheckContext {
+ universal_regions:
+ UniversalRegions {
+ defining_ty: DefiningTy::Const(def_id, _),
+ ..
+ },
+ ..
+ }) = self.borrowck_context
+ {
+ if tcx.is_static(*def_id).is_some() {
+ ConstraintCategory::UseAsStatic
+ } else {
+ ConstraintCategory::UseAsConst
+ }
+ } else {
+ ConstraintCategory::Return
+ }
+ }
Place::Local(l) if !mir.local_decls[l].is_user_variable.is_some() => {
ConstraintCategory::Boring
}
let locations = term_location.to_locations();
if let Err(terr) =
- self.sub_types_or_anon(sig.output(), dest_ty, locations, category)
- {
- span_mirbug!(
+ self.sub_types_or_anon(sig.output(), dest_ty, locations, category)
+ {
+ span_mirbug!(
self,
term,
"call dest mismatch ({:?} <- {:?}): {:?}",
sig.output(),
terr
);
- }
+ }
// When `#![feature(unsized_locals)]` is not enabled,
// this check is done at `check_local`.
sig: &ty::FnSig<'tcx>,
args: &[Operand<'tcx>],
term_location: Location,
+ from_hir_call: bool,
) {
debug!("check_call_inputs({:?}, {:?})", sig, args);
if args.len() < sig.inputs().len() || (args.len() > sig.inputs().len() && !sig.variadic) {
}
for (n, (fn_arg, op_arg)) in sig.inputs().iter().zip(args).enumerate() {
let op_arg_ty = op_arg.ty(mir, self.tcx());
- if let Err(terr) = self.sub_types(
- op_arg_ty,
- fn_arg,
- term_location.to_locations(),
- ConstraintCategory::CallArgument,
- ) {
+ let category = if from_hir_call {
+ ConstraintCategory::CallArgument
+ } else {
+ ConstraintCategory::Boring
+ };
+ if let Err(terr) =
+ self.sub_types(op_arg_ty, fn_arg, term_location.to_locations(), category)
+ {
span_mirbug!(
self,
term,
/// If this rvalue supports a user-given type annotation, then
/// extract and return it. This represents the final type of the
/// rvalue and will be unified with the inferred type.
- fn rvalue_user_ty(&self, rvalue: &Rvalue<'tcx>) -> Option<CanonicalTy<'tcx>> {
+ fn rvalue_user_ty(&self, rvalue: &Rvalue<'tcx>) -> Option<UserTypeAnnotation<'tcx>> {
match rvalue {
Rvalue::Use(_)
| Rvalue::Repeat(..)
aggregate_kind, location
);
- let instantiated_predicates = match aggregate_kind {
+ let instantiated_predicates = match aggregate_kind {
AggregateKind::Adt(def, _, substs, _, _) => {
tcx.predicates_of(def.did).instantiate(tcx, substs)
}
// desugaring. A closure gets desugared to a struct, and
// these extra requirements are basically like where
// clauses on the struct.
- AggregateKind::Closure(def_id, substs) => {
- self.prove_closure_bounds(tcx, *def_id, *substs, location)
- }
-
- AggregateKind::Generator(def_id, substs, _) => {
- tcx.predicates_of(*def_id).instantiate(tcx, substs.substs)
+ AggregateKind::Closure(def_id, ty::ClosureSubsts { substs })
+ | AggregateKind::Generator(def_id, ty::GeneratorSubsts { substs }, _) => {
+ self.prove_closure_bounds(tcx, *def_id, substs, location)
}
AggregateKind::Array(_) | AggregateKind::Tuple => ty::InstantiatedPredicates::empty(),
&mut self,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
def_id: DefId,
- substs: ty::ClosureSubsts<'tcx>,
+ substs: &'tcx Substs<'tcx>,
location: Location,
) -> ty::InstantiatedPredicates<'tcx> {
- if let Some(closure_region_requirements) =
- tcx.mir_borrowck(def_id).closure_requirements
- {
- let closure_constraints = closure_region_requirements.apply_requirements(
- tcx,
- location,
- def_id,
- substs,
- );
+ if let Some(closure_region_requirements) = tcx.mir_borrowck(def_id).closure_requirements {
+ let closure_constraints =
+ closure_region_requirements.apply_requirements(tcx, location, def_id, substs);
if let Some(ref mut borrowck_context) = self.borrowck_context {
let bounds_mapping = closure_constraints
.filter_map(|(idx, constraint)| {
let ty::OutlivesPredicate(k1, r2) =
constraint.no_late_bound_regions().unwrap_or_else(|| {
- bug!(
- "query_constraint {:?} contained bound regions",
- constraint,
- );
+ bug!("query_constraint {:?} contained bound regions", constraint,);
});
match k1.unpack() {
// constraint is r1: r2
let r1_vid = borrowck_context.universal_regions.to_region_vid(r1);
let r2_vid = borrowck_context.universal_regions.to_region_vid(r2);
- let outlives_requirements = &closure_region_requirements
- .outlives_requirements[idx];
+ let outlives_requirements =
+ &closure_region_requirements.outlives_requirements[idx];
Some((
(r1_vid, r2_vid),
(
})
.collect();
- let existing = borrowck_context.constraints
+ let existing = borrowck_context
+ .constraints
.closure_bounds_mapping
.insert(location, bounds_mapping);
- assert!(existing.is_none(), "Multiple closures at the same location.");
+ assert!(
+ existing.is_none(),
+ "Multiple closures at the same location."
+ );
}
self.push_region_constraints(
);
}
- tcx.predicates_of(def_id).instantiate(tcx, substs.substs)
+ tcx.predicates_of(def_id).instantiate(tcx, substs)
}
fn prove_trait_ref(