Skip to content

Commit

Permalink
Add new test for impl precedence and remove unnecessary coherence rul…
Browse files Browse the repository at this point in the history
…es that prevent the test from compiling.
  • Loading branch information
nikomatsakis authored and flaper87 committed Feb 22, 2015
1 parent 6d1844c commit 3343e9c
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 56 deletions.
57 changes: 1 addition & 56 deletions src/librustc_typeck/coherence/overlap.rs
Expand Up @@ -17,18 +17,12 @@ use middle::infer::{self, new_infer_ctxt};
use syntax::ast::{DefId};
use syntax::ast::{LOCAL_CRATE};
use syntax::ast;
use syntax::ast_util;
use syntax::visit;
use syntax::codemap::Span;
use util::ppaux::Repr;

pub fn check(tcx: &ty::ctxt) {
let mut overlap = OverlapChecker { tcx: tcx };
let overlap = OverlapChecker { tcx: tcx };
overlap.check_for_overlapping_impls();

// this secondary walk specifically checks for impls of defaulted
// traits, for which additional overlap rules exist
visit::walk_crate(&mut overlap, tcx.map.krate());
}

struct OverlapChecker<'cx, 'tcx:'cx> {
Expand Down Expand Up @@ -128,52 +122,3 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> {
self.tcx.map.span(impl_did.node)
}
}


impl<'cx, 'tcx,'v> visit::Visitor<'v> for OverlapChecker<'cx, 'tcx> {
fn visit_item(&mut self, item: &'v ast::Item) {
match item.node {
ast::ItemImpl(_, ast::ImplPolarity::Positive, _, Some(ref ast_trait_ref), _, _) => {
let trait_ref = ty::node_id_to_trait_ref(self.tcx, ast_trait_ref.ref_id);
match ty::trait_default_impl(self.tcx, trait_ref.def_id) {
Some(default_impl) => {
match trait_ref.self_ty().sty {
ty::ty_struct(..) | ty::ty_enum(..) => {},
_ => {
let impl_def_id = ast_util::local_def(item.id);
span_err!(self.tcx.sess, self.span_of_impl(impl_def_id), E0319,
"implementations for traits providing default \
implementations are only allowed on structs and enums");

self.report_overlap_note(impl_def_id, default_impl);
}
}
}
None => {}
}
}
ast::ItemDefaultImpl(_, _) => {
let impl_def_id = ast_util::local_def(item.id);
match ty::impl_trait_ref(self.tcx, impl_def_id) {
Some(ref trait_ref) => {
match ty::trait_default_impl(self.tcx, trait_ref.def_id) {
Some(other_impl) if other_impl != impl_def_id => {
self.report_overlap_error(trait_ref.def_id,
other_impl,
impl_def_id);
}
Some(_) => {}
None => {
self.tcx.sess.bug(
&format!("no default implementation recorded for `{:?}`",
item)[]);
}
}
}
_ => {}
}
}
_ => {}
}
}
}
32 changes: 32 additions & 0 deletions src/test/compile-fail/typeck-default-trait-impl-precedence.rs
@@ -0,0 +1,32 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Test that declaring that `&T` is `Defaulted` if `T:Signed` implies
// that other `&T` is NOT `Defaulted` if `T:Signed` does not hold. In
// other words, the `..` impl only applies if there are no existing
// impls whose types unify.

#![feature(optin_builtin_traits)]

use std::marker::MarkerTrait;

trait Defaulted : MarkerTrait { }
impl Defaulted for .. { }
impl<'a,T:Signed> Defaulted for &'a T { }
impl<'a,T:Signed> Defaulted for &'a mut T { }
fn is_defaulted<T:Defaulted>() { }

trait Signed : MarkerTrait { }
impl Signed for i32 { }

fn main() {
is_defaulted::<&'static i32>();
is_defaulted::<&'static u32>();
}

0 comments on commit 3343e9c

Please sign in to comment.