Skip to content

Commit d20b65b

Browse files
committed
auto merge of #18868 : nikomatsakis/rust/issue-17388-unbound-path-assoc-type, r=pcwalton
This fixes #17388. Note that we don't check type parameters in trait-references and so on, so we accept some nonsense (I opened #18865). (It may be easier to just add support for `T::Foo` and deprecate the qpath code until we can implement it more robustly using the trait lookup infrastructure, not sure.)
2 parents e09d986 + 420de27 commit d20b65b

18 files changed

+126
-192
lines changed

Diff for: src/librustc/lint/context.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -569,7 +569,8 @@ impl<'a, 'tcx> AstConv<'tcx> for Context<'a, 'tcx>{
569569
_: Option<ty::t>,
570570
trait_id: ast::DefId,
571571
associated_type_id: ast::DefId)
572-
-> ty::t {
572+
-> ty::t
573+
{
573574
// FIXME(pcwalton): This is wrong.
574575
let trait_def = self.get_trait_def(trait_id);
575576
let index = ty::associated_type_parameter_index(self.tcx,

Diff for: src/librustc/middle/resolve.rs

+4-59
Original file line numberDiff line numberDiff line change
@@ -633,6 +633,7 @@ enum TraitReferenceType {
633633
TraitDerivation, // trait T : SomeTrait { ... }
634634
TraitBoundingTypeParameter, // fn f<T:SomeTrait>() { ... }
635635
TraitObject, // Box<for<'a> SomeTrait>
636+
TraitQPath, // <T as SomeTrait>::
636637
}
637638

638639
impl NameBindings {
@@ -4532,6 +4533,7 @@ impl<'a> Resolver<'a> {
45324533
TraitImplementation => "implement",
45334534
TraitDerivation => "derive",
45344535
TraitObject => "reference",
4536+
TraitQPath => "extract an associated type from",
45354537
};
45364538

45374539
let msg = format!("attempt to {} a nonexistent trait `{}`", usage_str, path_str);
@@ -4969,65 +4971,8 @@ impl<'a> Resolver<'a> {
49694971
}
49704972

49714973
TyQPath(ref qpath) => {
4972-
self.resolve_type(&*qpath.for_type);
4973-
4974-
let current_module = self.current_module.clone();
4975-
let module_path: Vec<_> =
4976-
qpath.trait_name
4977-
.segments
4978-
.iter()
4979-
.map(|ps| ps.identifier.name)
4980-
.collect();
4981-
match self.resolve_module_path(
4982-
current_module,
4983-
module_path.as_slice(),
4984-
UseLexicalScope,
4985-
qpath.trait_name.span,
4986-
PathSearch) {
4987-
Success((ref module, _)) if module.kind.get() ==
4988-
TraitModuleKind => {
4989-
match self.resolve_definition_of_name_in_module(
4990-
(*module).clone(),
4991-
qpath.item_name.name,
4992-
TypeNS) {
4993-
ChildNameDefinition(def, lp) |
4994-
ImportNameDefinition(def, lp) => {
4995-
match def {
4996-
DefAssociatedTy(trait_type_id) => {
4997-
let def = DefAssociatedTy(
4998-
trait_type_id);
4999-
self.record_def(ty.id, (def, lp));
5000-
}
5001-
_ => {
5002-
self.resolve_error(
5003-
ty.span,
5004-
"not an associated type");
5005-
}
5006-
}
5007-
}
5008-
NoNameDefinition => {
5009-
self.resolve_error(ty.span,
5010-
"unresolved associated \
5011-
type");
5012-
}
5013-
}
5014-
}
5015-
Success(..) => self.resolve_error(ty.span, "not a trait"),
5016-
Indeterminate => {
5017-
self.session.span_bug(ty.span,
5018-
"indeterminate result when \
5019-
resolving associated type")
5020-
}
5021-
Failed(error) => {
5022-
let (span, help) = match error {
5023-
Some((span, msg)) => (span, format!("; {}", msg)),
5024-
None => (ty.span, String::new()),
5025-
};
5026-
self.resolve_error(span,
5027-
format!("unresolved trait: {}",
5028-
help).as_slice())
5029-
}
5030-
}
4974+
self.resolve_type(&*qpath.self_type);
4975+
self.resolve_trait_reference(ty.id, &*qpath.trait_ref, TraitQPath);
50314976
}
50324977

50334978
TyClosure(ref c) | TyProc(ref c) => {

Diff for: src/librustc/middle/subst.rs

+4
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ impl Substs {
100100
regions_is_noop && self.types.is_empty()
101101
}
102102

103+
pub fn type_for_def(&self, ty_param_def: &ty::TypeParameterDef) -> ty::t {
104+
*self.types.get(ty_param_def.space, ty_param_def.index)
105+
}
106+
103107
pub fn has_regions_escaping_depth(&self, depth: uint) -> bool {
104108
self.types.iter().any(|&t| ty::type_escapes_depth(t, depth)) || {
105109
match self.regions {

Diff for: src/librustc/middle/traits/mod.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use std::rc::Rc;
2525
use std::slice::Items;
2626
use syntax::ast;
2727
use syntax::codemap::{Span, DUMMY_SP};
28+
use util::common::ErrorReported;
2829

2930
pub use self::fulfill::FulfillmentContext;
3031
pub use self::select::SelectionContext;
@@ -95,10 +96,6 @@ pub enum ObligationCauseCode {
9596
FieldSized,
9697
}
9798

98-
// An error has already been reported to the user, so no need to continue checking.
99-
#[deriving(Clone,Show)]
100-
pub struct ErrorReported;
101-
10299
pub type Obligations = subst::VecPerParamSpace<Obligation>;
103100

104101
pub type Selection = Vtable<Obligation>;

Diff for: src/librustc/middle/traits/select.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ use self::Candidate::*;
1717
use self::BuiltinBoundConditions::*;
1818
use self::EvaluationResult::*;
1919

20-
use super::{ErrorReported};
2120
use super::{Obligation, ObligationCause};
2221
use super::{SelectionError, Unimplemented, Overflow,
2322
OutputTypeParameterMismatch};
@@ -38,6 +37,7 @@ use std::cell::RefCell;
3837
use std::collections::hash_map::HashMap;
3938
use std::rc::Rc;
4039
use syntax::ast;
40+
use util::common::ErrorReported;
4141
use util::ppaux::Repr;
4242

4343
pub struct SelectionContext<'cx, 'tcx:'cx> {

Diff for: src/librustc/middle/traits/util.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@ use std::fmt;
1818
use std::rc::Rc;
1919
use syntax::ast;
2020
use syntax::codemap::Span;
21+
use util::common::ErrorReported;
2122
use util::ppaux::Repr;
2223

23-
use super::{ErrorReported, Obligation, ObligationCause, VtableImpl,
24+
use super::{Obligation, ObligationCause, VtableImpl,
2425
VtableParam, VtableParamData, VtableImplData};
2526

2627
///////////////////////////////////////////////////////////////////////////

Diff for: src/librustc/middle/typeck/astconv.rs

+38-90
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,6 @@ fn ast_path_substs_for_ty<'tcx,AC,RS>(
207207
decl_def_id: ast::DefId,
208208
decl_generics: &ty::Generics,
209209
self_ty: Option<ty::t>,
210-
associated_ty: Option<ty::t>,
211210
path: &ast::Path)
212211
-> Substs
213212
where AC: AstConv<'tcx>, RS: RegionScope
@@ -243,7 +242,7 @@ fn ast_path_substs_for_ty<'tcx,AC,RS>(
243242
};
244243

245244
create_substs_for_ast_path(this, rscope, path.span, decl_def_id,
246-
decl_generics, self_ty, types, regions, associated_ty)
245+
decl_generics, self_ty, types, regions)
247246
}
248247

249248
fn create_substs_for_ast_path<'tcx,AC,RS>(
@@ -254,8 +253,7 @@ fn create_substs_for_ast_path<'tcx,AC,RS>(
254253
decl_generics: &ty::Generics,
255254
self_ty: Option<ty::t>,
256255
types: Vec<ty::t>,
257-
regions: Vec<ty::Region>,
258-
associated_ty: Option<ty::t>)
256+
regions: Vec<ty::Region>)
259257
-> Substs
260258
where AC: AstConv<'tcx>, RS: RegionScope
261259
{
@@ -366,9 +364,9 @@ fn create_substs_for_ast_path<'tcx,AC,RS>(
366364
substs.types.push(
367365
AssocSpace,
368366
this.associated_type_binding(span,
369-
associated_ty,
367+
self_ty,
370368
decl_def_id,
371-
param.def_id))
369+
param.def_id));
372370
}
373371

374372
return substs;
@@ -417,19 +415,17 @@ pub fn instantiate_poly_trait_ref<'tcx,AC,RS>(
417415
this: &AC,
418416
rscope: &RS,
419417
ast_trait_ref: &ast::PolyTraitRef,
420-
self_ty: Option<ty::t>,
421-
associated_type: Option<ty::t>)
418+
self_ty: Option<ty::t>)
422419
-> Rc<ty::TraitRef>
423420
where AC: AstConv<'tcx>, RS: RegionScope
424421
{
425-
instantiate_trait_ref(this, rscope, &ast_trait_ref.trait_ref, self_ty, associated_type)
422+
instantiate_trait_ref(this, rscope, &ast_trait_ref.trait_ref, self_ty)
426423
}
427424

428425
pub fn instantiate_trait_ref<'tcx,AC,RS>(this: &AC,
429426
rscope: &RS,
430427
ast_trait_ref: &ast::TraitRef,
431-
self_ty: Option<ty::t>,
432-
associated_type: Option<ty::t>)
428+
self_ty: Option<ty::t>)
433429
-> Rc<ty::TraitRef>
434430
where AC: AstConv<'tcx>,
435431
RS: RegionScope
@@ -444,8 +440,8 @@ pub fn instantiate_trait_ref<'tcx,AC,RS>(this: &AC,
444440
ast_trait_ref.path.span,
445441
ast_trait_ref.ref_id) {
446442
def::DefTrait(trait_def_id) => {
447-
let trait_ref = Rc::new(ast_path_to_trait_ref(this, rscope, trait_def_id, self_ty,
448-
associated_type, &ast_trait_ref.path));
443+
let trait_ref = Rc::new(ast_path_to_trait_ref(this, rscope, trait_def_id,
444+
self_ty, &ast_trait_ref.path));
449445
this.tcx().trait_refs.borrow_mut().insert(ast_trait_ref.ref_id,
450446
trait_ref.clone());
451447
trait_ref
@@ -463,7 +459,6 @@ fn ast_path_to_trait_ref<'tcx,AC,RS>(
463459
rscope: &RS,
464460
trait_def_id: ast::DefId,
465461
self_ty: Option<ty::t>,
466-
associated_type: Option<ty::t>,
467462
path: &ast::Path)
468463
-> ty::TraitRef
469464
where AC: AstConv<'tcx>, RS: RegionScope
@@ -493,8 +488,7 @@ fn ast_path_to_trait_ref<'tcx,AC,RS>(
493488
&trait_def.generics,
494489
self_ty,
495490
types,
496-
regions,
497-
associated_type);
491+
regions);
498492

499493
ty::TraitRef::new(trait_def_id, substs)
500494
}
@@ -517,7 +511,6 @@ pub fn ast_path_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
517511
did,
518512
&generics,
519513
None,
520-
None,
521514
path);
522515
let ty = decl_ty.subst(tcx, &substs);
523516
TypeAndSubsts { substs: substs, ty: ty }
@@ -558,7 +551,7 @@ pub fn ast_path_to_ty_relaxed<'tcx,AC,RS>(
558551
Substs::new(VecPerParamSpace::params_from_type(type_params),
559552
VecPerParamSpace::params_from_type(region_params))
560553
} else {
561-
ast_path_substs_for_ty(this, rscope, did, &generics, None, None, path)
554+
ast_path_substs_for_ty(this, rscope, did, &generics, None, path)
562555
};
563556

564557
let ty = decl_ty.subst(tcx, &substs);
@@ -725,7 +718,6 @@ fn mk_pointer<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
725718
rscope,
726719
trait_def_id,
727720
None,
728-
None,
729721
path);
730722
let empty_vec = [];
731723
let bounds = match *opt_bounds { None => empty_vec.as_slice(),
@@ -749,61 +741,37 @@ fn mk_pointer<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
749741
constr(ast_ty_to_ty(this, rscope, a_seq_ty))
750742
}
751743

752-
fn associated_ty_to_ty<'tcx,AC,RS>(this: &AC,
753-
rscope: &RS,
754-
trait_path: &ast::Path,
755-
for_ast_type: &ast::Ty,
756-
trait_type_id: ast::DefId,
757-
span: Span)
758-
-> ty::t
759-
where AC: AstConv<'tcx>, RS: RegionScope
744+
fn qpath_to_ty<'tcx,AC,RS>(this: &AC,
745+
rscope: &RS,
746+
ast_ty: &ast::Ty, // the TyQPath
747+
qpath: &ast::QPath)
748+
-> ty::t
749+
where AC: AstConv<'tcx>, RS: RegionScope
760750
{
761-
debug!("associated_ty_to_ty(trait_path={}, for_ast_type={}, trait_type_id={})",
762-
trait_path.repr(this.tcx()),
763-
for_ast_type.repr(this.tcx()),
764-
trait_type_id.repr(this.tcx()));
765-
766-
// Find the trait that this associated type belongs to.
767-
let trait_did = match ty::impl_or_trait_item(this.tcx(),
768-
trait_type_id).container() {
769-
ty::ImplContainer(_) => {
770-
this.tcx().sess.span_bug(span,
771-
"associated_ty_to_ty(): impl associated \
772-
types shouldn't go through this \
773-
function")
774-
}
775-
ty::TraitContainer(trait_id) => trait_id,
776-
};
751+
debug!("qpath_to_ty(ast_ty={})",
752+
ast_ty.repr(this.tcx()));
777753

778-
let for_type = ast_ty_to_ty(this, rscope, for_ast_type);
779-
if !this.associated_types_of_trait_are_valid(for_type, trait_did) {
780-
this.tcx().sess.span_err(span,
781-
"this associated type is not \
782-
allowed in this context");
783-
return ty::mk_err()
784-
}
754+
let self_type = ast_ty_to_ty(this, rscope, &*qpath.self_type);
755+
756+
debug!("qpath_to_ty: self_type={}", self_type.repr(this.tcx()));
785757

786-
let trait_ref = ast_path_to_trait_ref(this,
758+
let trait_ref = instantiate_trait_ref(this,
787759
rscope,
788-
trait_did,
789-
None,
790-
Some(for_type),
791-
trait_path);
792-
793-
debug!("associated_ty_to_ty(trait_ref={})",
794-
trait_ref.repr(this.tcx()));
795-
796-
let trait_def = this.get_trait_def(trait_did);
797-
for type_parameter in trait_def.generics.types.iter() {
798-
if type_parameter.def_id == trait_type_id {
799-
debug!("associated_ty_to_ty(type_parameter={} substs={})",
800-
type_parameter.repr(this.tcx()),
801-
trait_ref.substs.repr(this.tcx()));
802-
return *trait_ref.substs.types.get(type_parameter.space,
803-
type_parameter.index)
760+
&*qpath.trait_ref,
761+
Some(self_type));
762+
763+
debug!("qpath_to_ty: trait_ref={}", trait_ref.repr(this.tcx()));
764+
765+
let trait_def = this.get_trait_def(trait_ref.def_id);
766+
767+
for ty_param_def in trait_def.generics.types.get_slice(AssocSpace).iter() {
768+
if ty_param_def.name == qpath.item_name.name {
769+
debug!("qpath_to_ty: corresponding ty_param_def={}", ty_param_def);
770+
return trait_ref.substs.type_for_def(ty_param_def);
804771
}
805772
}
806-
this.tcx().sess.span_bug(span,
773+
774+
this.tcx().sess.span_bug(ast_ty.span,
807775
"this associated type didn't get added \
808776
as a parameter for some reason")
809777
}
@@ -930,7 +898,6 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
930898
rscope,
931899
trait_def_id,
932900
None,
933-
None,
934901
path);
935902
let empty_bounds: &[ast::TyParamBound] = &[];
936903
let ast_bounds = match *bounds {
@@ -995,26 +962,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
995962
}
996963
}
997964
ast::TyQPath(ref qpath) => {
998-
match tcx.def_map.borrow().get(&ast_ty.id) {
999-
None => {
1000-
tcx.sess.span_bug(ast_ty.span,
1001-
"unbound qualified path")
1002-
}
1003-
Some(&def::DefAssociatedTy(trait_type_id)) => {
1004-
associated_ty_to_ty(this,
1005-
rscope,
1006-
&qpath.trait_name,
1007-
&*qpath.for_type,
1008-
trait_type_id,
1009-
ast_ty.span)
1010-
}
1011-
Some(_) => {
1012-
tcx.sess.span_err(ast_ty.span,
1013-
"this qualified path does not name \
1014-
an associated type");
1015-
ty::mk_err()
1016-
}
1017-
}
965+
qpath_to_ty(this, rscope, ast_ty, &**qpath)
1018966
}
1019967
ast::TyFixedLengthVec(ref ty, ref e) => {
1020968
match const_eval::eval_const_expr_partial(tcx, &**e) {
@@ -1410,7 +1358,7 @@ fn conv_ty_poly_trait_ref<'tcx, AC, RS>(
14101358

14111359
let main_trait_bound = match partitioned_bounds.trait_bounds.remove(0) {
14121360
Some(trait_bound) => {
1413-
Some(instantiate_poly_trait_ref(this, rscope, trait_bound, None, None))
1361+
Some(instantiate_poly_trait_ref(this, rscope, trait_bound, None))
14141362
}
14151363
None => {
14161364
this.tcx().sess.span_err(

0 commit comments

Comments
 (0)