Skip to content

Commit c7b5f4d

Browse files
committed
Auto merge of #58305 - scalexm:chalk-continued, r=nikomatsakis
(WIP) Small fixes in chalkification Small fixes around region constraints and builtin impls. There are still some type inference errors, for example the following code errors out: ```rust fn main() { let mut x: Vec<i32> = Vec::new(); // ^^^^^^^^ cannot infer type for `std::vec::Vec<_>` } ``` but explicitly specifying `Vec::<i32>::new` works. With these few fixes, the following code now passes type-checking: ```rust fn main() { let mut x: Vec<i32> = Vec::<i32>::new(); x.push(5); println!("{:?}", x); } ``` I also fixed the implied bounds bug as discussed on Zulip and in rust-lang/chalk#206 cc @tmandry r? @nikomatsakis
2 parents fb5ed48 + ca5a212 commit c7b5f4d

File tree

13 files changed

+946
-696
lines changed

13 files changed

+946
-696
lines changed

src/librustc/infer/nll_relate/mod.rs

+159-34
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,14 @@
2222
//! constituents)
2323
2424
use crate::infer::InferCtxt;
25+
use crate::traits::DomainGoal;
26+
use crate::ty::error::TypeError;
2527
use crate::ty::fold::{TypeFoldable, TypeVisitor};
2628
use crate::ty::relate::{self, Relate, RelateResult, TypeRelation};
2729
use crate::ty::subst::Kind;
2830
use crate::ty::{self, Ty, TyCtxt};
29-
use crate::ty::error::TypeError;
30-
use crate::traits::DomainGoal;
3131
use rustc_data_structures::fx::FxHashMap;
32+
use std::fmt::Debug;
3233

3334
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
3435
pub enum NormalizationStrategy {
@@ -239,6 +240,7 @@ where
239240
first_free_index: ty::DebruijnIndex,
240241
scopes: &[BoundRegionScope<'tcx>],
241242
) -> ty::Region<'tcx> {
243+
debug!("replace_bound_regions(scopes={:?})", scopes);
242244
if let ty::ReLateBound(debruijn, br) = r {
243245
Self::lookup_bound_region(*debruijn, br, first_free_index, scopes)
244246
} else {
@@ -265,15 +267,17 @@ where
265267
fn relate_projection_ty(
266268
&mut self,
267269
projection_ty: ty::ProjectionTy<'tcx>,
268-
value_ty: ty::Ty<'tcx>
270+
value_ty: ty::Ty<'tcx>,
269271
) -> Ty<'tcx> {
270272
use crate::infer::type_variable::TypeVariableOrigin;
271273
use crate::traits::WhereClause;
272274
use syntax_pos::DUMMY_SP;
273275

274276
match value_ty.sty {
275277
ty::Projection(other_projection_ty) => {
276-
let var = self.infcx.next_ty_var(TypeVariableOrigin::MiscVariable(DUMMY_SP));
278+
let var = self
279+
.infcx
280+
.next_ty_var(TypeVariableOrigin::MiscVariable(DUMMY_SP));
277281
self.relate_projection_ty(projection_ty, var);
278282
self.relate_projection_ty(other_projection_ty, var);
279283
var
@@ -284,32 +288,55 @@ where
284288
projection_ty,
285289
ty: value_ty,
286290
};
287-
self.delegate.push_domain_goal(
288-
DomainGoal::Holds(WhereClause::ProjectionEq(projection))
289-
);
291+
self.delegate
292+
.push_domain_goal(DomainGoal::Holds(WhereClause::ProjectionEq(projection)));
290293
value_ty
291294
}
292295
}
293296
}
294297

295-
/// Relate a type inference variable with a value type.
296-
fn relate_ty_var(
298+
/// Relate a type inference variable with a value type. This works
299+
/// by creating a "generalization" G of the value where all the
300+
/// lifetimes are replaced with fresh inference values. This
301+
/// genearlization G becomes the value of the inference variable,
302+
/// and is then related in turn to the value. So e.g. if you had
303+
/// `vid = ?0` and `value = &'a u32`, we might first instantiate
304+
/// `?0` to a type like `&'0 u32` where `'0` is a fresh variable,
305+
/// and then relate `&'0 u32` with `&'a u32` (resulting in
306+
/// relations between `'0` and `'a`).
307+
///
308+
/// The variable `pair` can be either a `(vid, ty)` or `(ty, vid)`
309+
/// -- in other words, it is always a (unresolved) inference
310+
/// variable `vid` and a type `ty` that are being related, but the
311+
/// vid may appear either as the "a" type or the "b" type,
312+
/// depending on where it appears in the tuple. The trait
313+
/// `VidValuePair` lets us work with the vid/type while preserving
314+
/// the "sidedness" when necessary -- the sidedness is relevant in
315+
/// particular for the variance and set of in-scope things.
316+
fn relate_ty_var<PAIR: VidValuePair<'tcx>>(
297317
&mut self,
298-
vid: ty::TyVid,
299-
value_ty: Ty<'tcx>
318+
pair: PAIR,
300319
) -> RelateResult<'tcx, Ty<'tcx>> {
301-
debug!("relate_ty_var(vid={:?}, value_ty={:?})", vid, value_ty);
320+
debug!("relate_ty_var({:?})", pair);
302321

322+
let vid = pair.vid();
323+
let value_ty = pair.value_ty();
324+
325+
// FIXME -- this logic assumes invariance, but that is wrong.
326+
// This only presently applies to chalk integration, as NLL
327+
// doesn't permit type variables to appear on both sides (and
328+
// doesn't use lazy norm).
303329
match value_ty.sty {
304330
ty::Infer(ty::TyVar(value_vid)) => {
305331
// Two type variables: just equate them.
306-
self.infcx.type_variables.borrow_mut().equate(vid, value_vid);
332+
self.infcx
333+
.type_variables
334+
.borrow_mut()
335+
.equate(vid, value_vid);
307336
return Ok(value_ty);
308337
}
309338

310-
ty::Projection(projection_ty)
311-
if D::normalization() == NormalizationStrategy::Lazy =>
312-
{
339+
ty::Projection(projection_ty) if D::normalization() == NormalizationStrategy::Lazy => {
313340
return Ok(self.relate_projection_ty(projection_ty, self.infcx.tcx.mk_ty_var(vid)));
314341
}
315342

@@ -326,19 +353,22 @@ where
326353
assert!(!generalized_ty.has_infer_types());
327354
}
328355

329-
self.infcx.type_variables.borrow_mut().instantiate(vid, generalized_ty);
356+
self.infcx
357+
.type_variables
358+
.borrow_mut()
359+
.instantiate(vid, generalized_ty);
330360

331361
// The generalized values we extract from `canonical_var_values` have
332362
// been fully instantiated and hence the set of scopes we have
333363
// doesn't matter -- just to be sure, put an empty vector
334364
// in there.
335-
let old_a_scopes = ::std::mem::replace(&mut self.a_scopes, vec![]);
365+
let old_a_scopes = ::std::mem::replace(pair.vid_scopes(self), vec![]);
336366

337367
// Relate the generalized kind to the original one.
338-
let result = self.relate(&generalized_ty, &value_ty);
368+
let result = pair.relate_generalized_ty(self, generalized_ty);
339369

340370
// Restore the old scopes now.
341-
self.a_scopes = old_a_scopes;
371+
*pair.vid_scopes(self) = old_a_scopes;
342372

343373
debug!("relate_ty_var: complete, result = {:?}", result);
344374
result
@@ -347,7 +377,7 @@ where
347377
fn generalize_value<T: Relate<'tcx>>(
348378
&mut self,
349379
value: T,
350-
for_vid: ty::TyVid
380+
for_vid: ty::TyVid,
351381
) -> RelateResult<'tcx, T> {
352382
let universe = self.infcx.probe_ty_var(for_vid).unwrap_err();
353383

@@ -364,6 +394,104 @@ where
364394
}
365395
}
366396

397+
/// When we instantiate a inference variable with a value in
398+
/// `relate_ty_var`, we always have the pair of a `TyVid` and a `Ty`,
399+
/// but the ordering may vary (depending on whether the inference
400+
/// variable was found on the `a` or `b` sides). Therefore, this trait
401+
/// allows us to factor out common code, while preserving the order
402+
/// when needed.
403+
trait VidValuePair<'tcx>: Debug {
404+
/// Extract the inference variable (which could be either the
405+
/// first or second part of the tuple).
406+
fn vid(&self) -> ty::TyVid;
407+
408+
/// Extract the value it is being related to (which will be the
409+
/// opposite part of the tuple from the vid).
410+
fn value_ty(&self) -> Ty<'tcx>;
411+
412+
/// Extract the scopes that apply to whichever side of the tuple
413+
/// the vid was found on. See the comment where this is called
414+
/// for more details on why we want them.
415+
fn vid_scopes<D: TypeRelatingDelegate<'tcx>>(
416+
&self,
417+
relate: &'r mut TypeRelating<'_, '_, 'tcx, D>,
418+
) -> &'r mut Vec<BoundRegionScope<'tcx>>;
419+
420+
/// Given a generalized type G that should replace the vid, relate
421+
/// G to the value, putting G on whichever side the vid would have
422+
/// appeared.
423+
fn relate_generalized_ty<D>(
424+
&self,
425+
relate: &mut TypeRelating<'_, '_, 'tcx, D>,
426+
generalized_ty: Ty<'tcx>,
427+
) -> RelateResult<'tcx, Ty<'tcx>>
428+
where
429+
D: TypeRelatingDelegate<'tcx>;
430+
}
431+
432+
impl VidValuePair<'tcx> for (ty::TyVid, Ty<'tcx>) {
433+
fn vid(&self) -> ty::TyVid {
434+
self.0
435+
}
436+
437+
fn value_ty(&self) -> Ty<'tcx> {
438+
self.1
439+
}
440+
441+
fn vid_scopes<D>(
442+
&self,
443+
relate: &'r mut TypeRelating<'_, '_, 'tcx, D>,
444+
) -> &'r mut Vec<BoundRegionScope<'tcx>>
445+
where
446+
D: TypeRelatingDelegate<'tcx>,
447+
{
448+
&mut relate.a_scopes
449+
}
450+
451+
fn relate_generalized_ty<D>(
452+
&self,
453+
relate: &mut TypeRelating<'_, '_, 'tcx, D>,
454+
generalized_ty: Ty<'tcx>,
455+
) -> RelateResult<'tcx, Ty<'tcx>>
456+
where
457+
D: TypeRelatingDelegate<'tcx>,
458+
{
459+
relate.relate(&generalized_ty, &self.value_ty())
460+
}
461+
}
462+
463+
// In this case, the "vid" is the "b" type.
464+
impl VidValuePair<'tcx> for (Ty<'tcx>, ty::TyVid) {
465+
fn vid(&self) -> ty::TyVid {
466+
self.1
467+
}
468+
469+
fn value_ty(&self) -> Ty<'tcx> {
470+
self.0
471+
}
472+
473+
fn vid_scopes<D>(
474+
&self,
475+
relate: &'r mut TypeRelating<'_, '_, 'tcx, D>,
476+
) -> &'r mut Vec<BoundRegionScope<'tcx>>
477+
where
478+
D: TypeRelatingDelegate<'tcx>,
479+
{
480+
&mut relate.b_scopes
481+
}
482+
483+
fn relate_generalized_ty<D>(
484+
&self,
485+
relate: &mut TypeRelating<'_, '_, 'tcx, D>,
486+
generalized_ty: Ty<'tcx>,
487+
) -> RelateResult<'tcx, Ty<'tcx>>
488+
where
489+
D: TypeRelatingDelegate<'tcx>,
490+
{
491+
relate.relate(&self.value_ty(), &generalized_ty)
492+
}
493+
}
494+
367495
impl<D> TypeRelation<'me, 'gcx, 'tcx> for TypeRelating<'me, 'gcx, 'tcx, D>
368496
where
369497
D: TypeRelatingDelegate<'tcx>,
@@ -421,11 +549,11 @@ where
421549
// Forbid inference variables in the RHS.
422550
bug!("unexpected inference var {:?}", b)
423551
} else {
424-
self.relate_ty_var(vid, a)
552+
self.relate_ty_var((a, vid))
425553
}
426554
}
427555

428-
(&ty::Infer(ty::TyVar(vid)), _) => self.relate_ty_var(vid, b),
556+
(&ty::Infer(ty::TyVar(vid)), _) => self.relate_ty_var((vid, b)),
429557

430558
(&ty::Projection(projection_ty), _)
431559
if D::normalization() == NormalizationStrategy::Lazy =>
@@ -752,7 +880,9 @@ where
752880
drop(variables);
753881
self.relate(&u, &u)
754882
}
755-
TypeVariableValue::Unknown { universe: _universe } => {
883+
TypeVariableValue::Unknown {
884+
universe: _universe,
885+
} => {
756886
if self.ambient_variance == ty::Bivariant {
757887
// FIXME: we may need a WF predicate (related to #54105).
758888
}
@@ -767,17 +897,15 @@ where
767897
let u = self.tcx().mk_ty_var(new_var_id);
768898
debug!(
769899
"generalize: replacing original vid={:?} with new={:?}",
770-
vid,
771-
u
900+
vid, u
772901
);
773902
return Ok(u);
774903
}
775904
}
776905
}
777906
}
778907

779-
ty::Infer(ty::IntVar(_)) |
780-
ty::Infer(ty::FloatVar(_)) => {
908+
ty::Infer(ty::IntVar(_)) | ty::Infer(ty::FloatVar(_)) => {
781909
// No matter what mode we are in,
782910
// integer/floating-point types must be equal to be
783911
// relatable.
@@ -788,19 +916,16 @@ where
788916
if self.universe.cannot_name(placeholder.universe) {
789917
debug!(
790918
"TypeGeneralizer::tys: root universe {:?} cannot name\
791-
placeholder in universe {:?}",
792-
self.universe,
793-
placeholder.universe
919+
placeholder in universe {:?}",
920+
self.universe, placeholder.universe
794921
);
795922
Err(TypeError::Mismatch)
796923
} else {
797924
Ok(a)
798925
}
799926
}
800927

801-
_ => {
802-
relate::super_relate_tys(self, a, a)
803-
}
928+
_ => relate::super_relate_tys(self, a, a),
804929
}
805930
}
806931

0 commit comments

Comments
 (0)