diff options
| author | Matthew Jasper <mjjasper1@gmail.com> | 2019-01-17 21:07:27 +0000 |
|---|---|---|
| committer | Matthew Jasper <mjjasper1@gmail.com> | 2019-01-19 16:30:45 +0000 |
| commit | c76e55747b88949634438b6ed2e3f4dd24e799fc (patch) | |
| tree | f4a7d5ae1604a47344849efa861fd1b0e9f761bb /src/librustc_mir/borrow_check | |
| parent | 65fe2516346f10dc8d670e9fdfbd4e4f99a5b34b (diff) | |
| download | rust-c76e55747b88949634438b6ed2e3f4dd24e799fc.tar.gz rust-c76e55747b88949634438b6ed2e3f4dd24e799fc.zip | |
Type check unnanotated constant items with NLL
Diffstat (limited to 'src/librustc_mir/borrow_check')
| -rw-r--r-- | src/librustc_mir/borrow_check/nll/type_check/mod.rs | 111 |
1 files changed, 49 insertions, 62 deletions
diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 9ed1d49d05b..3e6aa358ee0 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -35,7 +35,7 @@ use rustc::traits::query::type_op::custom::CustomTypeOp; use rustc::traits::query::{Fallible, NoSolution}; use rustc::traits::{ObligationCause, PredicateObligations}; use rustc::ty::fold::TypeFoldable; -use rustc::ty::subst::{Subst, Substs, UnpackedKind}; +use rustc::ty::subst::{Subst, Substs, UnpackedKind, UserSubsts}; use rustc::ty::{ self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind, UserType, CanonicalUserTypeAnnotation, UserTypeAnnotationIndex, @@ -283,7 +283,7 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> { location.to_locations(), ConstraintCategory::Boring, ) { - let annotation = self.cx.instantiated_type_annotations[&annotation_index]; + let annotation = &self.mir.user_type_annotations[annotation_index]; span_mirbug!( self, constant, @@ -293,6 +293,39 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> { terr, ); } + } else { + match *constant.literal { + ty::LazyConst::Unevaluated(def_id, substs) => { + if let Err(terr) = self.cx.fully_perform_op( + location.to_locations(), + ConstraintCategory::Boring, + self.cx.param_env.and(type_op::ascribe_user_type::AscribeUserType::new( + constant.ty, def_id, UserSubsts { substs, user_self_ty: None }, + )), + ) { + span_mirbug!( + self, + constant, + "bad constant type {:?} ({:?})", + constant, + terr + ); + } + } + ty::LazyConst::Evaluated(lit) => { + if let ty::FnDef(def_id, substs) = lit.ty.sty { + let tcx = self.tcx(); + + let instantiated_predicates = tcx + .predicates_of(def_id) + .instantiate(tcx, substs); + self.cx.normalize_and_prove_instantiated_predicates( + instantiated_predicates, + location.to_locations(), + ); + } + } + } } } @@ -374,8 +407,9 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { } } - /// Checks that the constant's `ty` field matches up with what - /// would be expected from its literal. + /// Checks that the constant's `ty` field matches up with what would be + /// expected from its literal. Unevaluated constants and well-formed + /// constraints are checked by `visit_constant`. fn sanitize_constant(&mut self, constant: &Constant<'tcx>, location: Location) { debug!( "sanitize_constant(constant={:?}, location={:?})", @@ -387,35 +421,6 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { ty::LazyConst::Unevaluated(..) => return, }; - // FIXME(#46702) -- We need some way to get the predicates - // associated with the "pre-evaluated" form of the - // constant. For example, consider that the constant - // may have associated constant projections (`<Foo as - // Trait<'a, 'b>>::SOME_CONST`) that impose - // constraints on `'a` and `'b`. These constraints - // would be lost if we just look at the normalized - // value. - if let ty::FnDef(def_id, substs) = literal.ty.sty { - let tcx = self.tcx(); - let type_checker = &mut self.cx; - - // FIXME -- For now, use the substitutions from - // `value.ty` rather than `value.val`. The - // renumberer will rewrite them to independent - // sets of regions; in principle, we ought to - // derive the type of the `value.val` from "first - // principles" and equate with value.ty, but as we - // are transitioning to the miri-based system, we - // don't have a handy function for that, so for - // now we just ignore `value.val` regions. - - let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs); - type_checker.normalize_and_prove_instantiated_predicates( - instantiated_predicates, - location.to_locations(), - ); - } - debug!("sanitize_constant: expected_ty={:?}", literal.ty); if let Err(terr) = self.cx.eq_types( @@ -740,15 +745,6 @@ struct TypeChecker<'a, 'gcx: 'tcx, 'tcx: 'a> { reported_errors: FxHashSet<(Ty<'tcx>, Span)>, borrowck_context: Option<&'a mut BorrowCheckContext<'a, 'tcx>>, universal_region_relations: Option<&'a UniversalRegionRelations<'tcx>>, - /// For each user-type annotation (identified by a UserTypeAnnotationIndex), we create - /// an "instantiated" version at the beginning of type check, which replaces each - /// canonical variable with a fresh inference variable. These instantiated versions are - /// stored either in this field or in user_substs, depending on the kind of user-type - /// annotation. They are then referenced by the code which has the job of enforcing these - /// annotations. Part of the reason for this setup is that it allows us to enforce basic - /// WF criteria on the types even if the code that referenced them is dead - /// code (see #54943). - instantiated_type_annotations: FxHashMap<UserTypeAnnotationIndex, Ty<'tcx>>, } struct BorrowCheckContext<'a, 'tcx: 'a> { @@ -905,23 +901,19 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { borrowck_context, reported_errors: Default::default(), universal_region_relations, - instantiated_type_annotations: Default::default(), }; - checker.instantiate_user_type_annotations(); + checker.check_user_type_annotations(); checker } - /// Instantiate canonical types from user type annotations in the `Mir` into the - /// `TypeChecker`. Used when relating user type annotations and when checking if - /// annotations are well-formed. - fn instantiate_user_type_annotations(&mut self) { + /// Equate the inferred type and the annotated type for user type annotations + fn check_user_type_annotations(&mut self) { debug!( - "instantiate_user_type_annotations: user_type_annotations={:?}", + "check_user_type_annotations: user_type_annotations={:?}", self.mir.user_type_annotations ); - for annotation_index in self.mir.user_type_annotations.indices() { - let CanonicalUserTypeAnnotation { span, ref user_ty, inferred_ty } = - self.mir.user_type_annotations[annotation_index]; + for user_annotation in &self.mir.user_type_annotations { + let CanonicalUserTypeAnnotation { span, ref user_ty, inferred_ty } = *user_annotation; let (annotation, _) = self.infcx.instantiate_canonical_with_fresh_inference_vars( span, user_ty ); @@ -937,7 +929,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { ) { span_mirbug!( self, - self.mir.user_type_annotations[annotation_index], + user_annotation, "bad user type ({:?} = {:?}): {:?}", ty, inferred_ty, @@ -961,7 +953,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { ) { span_mirbug!( self, - self.mir.user_type_annotations[annotation_index], + user_annotation, "bad user type AscribeUserType({:?}, {:?} {:?}): {:?}", inferred_ty, def_id, @@ -971,12 +963,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } }, } - self.instantiated_type_annotations.insert(annotation_index, inferred_ty); } - debug!( - "instantiate_user_type_annotations: instantiated_type_annotations={:?}", - self.instantiated_type_annotations, - ); } /// Given some operation `op` that manipulates types, proves @@ -1108,7 +1095,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { a, v, user_ty, locations, ); - let annotated_type = self.instantiated_type_annotations[&user_ty.base]; + let annotated_type = self.mir.user_type_annotations[user_ty.base].inferred_ty; let mut curr_projected_ty = PlaceTy::from_ty(annotated_type); let tcx = self.infcx.tcx; @@ -1293,7 +1280,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { location.to_locations(), ConstraintCategory::Boring, ) { - let annotation = self.instantiated_type_annotations[&annotation_index]; + let annotation = &mir.user_type_annotations[annotation_index]; span_mirbug!( self, stmt, @@ -1352,7 +1339,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { Locations::All(stmt.source_info.span), ConstraintCategory::TypeAnnotation, ) { - let annotation = self.instantiated_type_annotations[&projection.base]; + let annotation = &mir.user_type_annotations[projection.base]; span_mirbug!( self, stmt, |
