Skip to content

Commit 635a959

Browse files
committed
rustc: Make coherence aware of multiple-traits-per-impl
1 parent 5506bf1 commit 635a959

File tree

1 file changed

+80
-97
lines changed

1 file changed

+80
-97
lines changed

src/rustc/middle/typeck/coherence.rs

Lines changed: 80 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ fn get_base_type_def_id(inference_context: infer_ctxt,
111111
class CoherenceInfo {
112112
// Contains implementations of methods that are inherent to a type.
113113
// Methods in these implementations don't need to be exported.
114+
114115
let inherent_methods: hashmap<def_id,@dvec<@Impl>>;
115116

116117
// Contains implementations of methods associated with a trait. For these,
@@ -129,14 +130,17 @@ class CoherenceChecker {
129130

130131
// A mapping from implementations to the corresponding base type
131132
// definition ID.
133+
132134
let base_type_def_ids: hashmap<def_id,def_id>;
133135

134136
// A set of implementations in privileged scopes; i.e. those
135137
// implementations that are defined in the same scope as their base types.
138+
136139
let privileged_implementations: hashmap<node_id,()>;
137140

138141
// The set of types that we are currently in the privileged scope of. This
139142
// is used while we traverse the AST while checking privileged scopes.
143+
140144
let privileged_types: hashmap<def_id,()>;
141145

142146
new(crate_context: @crate_ctxt) {
@@ -158,17 +162,7 @@ class CoherenceChecker {
158162

159163
alt item.node {
160164
item_impl(_, associated_traits, self_type, _) {
161-
// XXX: Accept an array of traits.
162-
let optional_associated_trait;
163-
if associated_traits.len() == 0 {
164-
optional_associated_trait = none;
165-
} else {
166-
optional_associated_trait =
167-
some(associated_traits[0]);
168-
}
169-
170-
self.check_implementation(item,
171-
optional_associated_trait);
165+
self.check_implementation(item, associated_traits);
172166
}
173167
_ {
174168
// Nothing to do.
@@ -195,47 +189,49 @@ class CoherenceChecker {
195189
self.add_external_crates();
196190
}
197191

198-
fn check_implementation(item: @item,
199-
optional_associated_trait: option<@trait_ref>) {
200-
192+
fn check_implementation(item: @item, associated_traits: ~[@trait_ref]) {
201193
let self_type = self.crate_context.tcx.tcache.get(local_def(item.id));
202-
alt optional_associated_trait {
203-
none {
204-
#debug("(checking implementation) no associated trait for \
205-
item '%s'",
206-
*item.ident);
207-
208-
alt get_base_type_def_id(self.inference_context,
209-
item.span,
210-
self_type.ty) {
211-
none {
212-
let session = self.crate_context.tcx.sess;
213-
session.span_err(item.span,
214-
~"no base type found for inherent \
215-
implementation; implement a \
216-
trait instead");
217-
}
218-
some(_) {
219-
// Nothing to do.
220-
}
194+
195+
// If there are no traits, then this implementation must have a
196+
// base type.
197+
198+
if associated_traits.len() == 0 {
199+
#debug("(checking implementation) no associated traits for item \
200+
'%s'",
201+
*item.ident);
202+
203+
alt get_base_type_def_id(self.inference_context,
204+
item.span,
205+
self_type.ty) {
206+
none {
207+
let session = self.crate_context.tcx.sess;
208+
session.span_err(item.span,
209+
~"no base type found for inherent \
210+
implementation; implement a \
211+
trait instead");
212+
}
213+
some(_) {
214+
// Nothing to do.
221215
}
222216
}
223-
some(associated_trait) {
224-
let def = self.crate_context.tcx.def_map.get
225-
(associated_trait.ref_id);
226-
#debug("(checking implementation) adding impl for trait \
227-
'%s', item '%s'",
228-
ast_map::node_id_to_str(self.crate_context.tcx.items,
229-
associated_trait.ref_id),
230-
*item.ident);
217+
}
231218

232-
let implementation = self.create_impl_from_item(item);
233-
self.add_trait_method(def_id_of_def(def), implementation);
234-
}
219+
for associated_traits.each |associated_trait| {
220+
let def = self.crate_context.tcx.def_map.get
221+
(associated_trait.ref_id);
222+
#debug("(checking implementation) adding impl for trait \
223+
'%s', item '%s'",
224+
ast_map::node_id_to_str(self.crate_context.tcx.items,
225+
associated_trait.ref_id),
226+
*item.ident);
227+
228+
let implementation = self.create_impl_from_item(item);
229+
self.add_trait_method(def_id_of_def(def), implementation);
235230
}
236231

237232
// Add the implementation to the mapping from implementation to base
238233
// type def ID, if there is a base type for this implementation.
234+
239235
alt get_base_type_def_id(self.inference_context,
240236
item.span,
241237
self_type.ty) {
@@ -326,6 +322,7 @@ class CoherenceChecker {
326322

327323
// Converts a polytype to a monotype by replacing all parameters with
328324
// type variables.
325+
329326
fn universally_quantify_polytype(polytype: ty_param_bounds_and_ty) -> t {
330327
let self_region =
331328
if !polytype.rp {none}
@@ -385,14 +382,6 @@ class CoherenceChecker {
385382
}
386383
}
387384
item_impl(_, associated_traits, _, _) {
388-
// XXX: Accept an array of traits.
389-
let optional_trait_ref;
390-
if associated_traits.len() == 0 {
391-
optional_trait_ref = none;
392-
} else {
393-
optional_trait_ref = some(associated_traits[0]);
394-
}
395-
396385
alt self.base_type_def_ids.find(local_def(item.id)) {
397386
none {
398387
// Nothing to do.
@@ -411,56 +400,50 @@ class CoherenceChecker {
411400
} else {
412401
// This implementation is not in scope of
413402
// its base type. This still might be OK
414-
// if the trait is defined in the same
403+
// if the traits are defined in the same
415404
// crate.
416405

417-
alt optional_trait_ref {
418-
none {
419-
// There is no trait to implement,
420-
// so this is an error.
406+
if associated_traits.len() == 0 {
407+
// There is no trait to implement, so
408+
// this is an error.
409+
410+
let session =
411+
self.crate_context.tcx.sess;
412+
session.span_err(item.span,
413+
~"cannot implement \
414+
inherent methods \
415+
for a type outside \
416+
the scope the type \
417+
was defined in; \
418+
define and \
419+
implement a trait \
420+
instead");
421+
}
421422

422-
let session =
423-
self.crate_context.tcx.sess;
423+
for associated_traits.each |trait_ref| {
424+
// This is OK if and only if the
425+
// trait was defined in this
426+
// crate.
427+
428+
let def_map = self.crate_context.tcx
429+
.def_map;
430+
let trait_def = def_map.get
431+
(trait_ref.ref_id);
432+
let trait_id =
433+
def_id_of_def(trait_def);
434+
if trait_id.crate != local_crate {
435+
let session = self.crate_context
436+
.tcx.sess;
424437
session.span_err(item.span,
425438
~"cannot \
426-
implement \
427-
inherent \
428-
methods for a \
429-
type outside \
430-
the scope the \
431-
type was \
432-
defined in; \
433-
define and \
434-
implement a \
435-
trait instead");
436-
}
437-
some(trait_ref) {
438-
// This is OK if and only if the
439-
// trait was defined in this
440-
// crate.
441-
442-
let def_map = self.crate_context
443-
.tcx.def_map;
444-
let trait_def =
445-
def_map.get(trait_ref.ref_id);
446-
let trait_id =
447-
def_id_of_def(trait_def);
448-
if trait_id.crate != local_crate {
449-
let session = self
450-
.crate_context.tcx.sess;
451-
session.span_err(item.span,
452-
~"cannot \
453-
provide \
454-
an \
455-
extension \
456-
implementa\
457-
tion \
458-
for a \
459-
trait not \
460-
defined \
461-
in this \
462-
crate");
463-
}
439+
provide an \
440+
extension \
441+
implementa\
442+
tion \
443+
for a trait \
444+
not defined \
445+
in this \
446+
crate");
464447
}
465448
}
466449
}

0 commit comments

Comments
 (0)