Skip to content

Commit 9c5cfea

Browse files
committed
traits: consider whether origin is RFC1214 when caching, ensuring
that the test rfc1214-warn-and-error.rs reports an error
1 parent fb1b6fc commit 9c5cfea

File tree

4 files changed

+68
-11
lines changed

4 files changed

+68
-11
lines changed

src/librustc/middle/traits/fulfill.rs

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,13 @@ use super::ObligationCause;
2727
use super::ObligationCauseCode;
2828
use super::PredicateObligation;
2929
use super::project;
30+
use super::RFC1214Warning;
3031
use super::select::SelectionContext;
3132
use super::Unimplemented;
3233
use super::util::predicate_for_builtin_bound;
3334

3435
pub struct FulfilledPredicates<'tcx> {
35-
set: HashSet<ty::Predicate<'tcx>>
36+
set: HashSet<(RFC1214Warning, ty::Predicate<'tcx>)>
3637
}
3738

3839
/// The fulfillment context is used to drive trait resolution. It
@@ -190,7 +191,9 @@ impl<'tcx> FulfillmentContext<'tcx> {
190191

191192
assert!(!obligation.has_escaping_regions());
192193

193-
if self.is_duplicate_or_add(infcx.tcx, &obligation.predicate) {
194+
let w = RFC1214Warning(obligation.cause.code.is_rfc1214());
195+
196+
if self.is_duplicate_or_add(infcx.tcx, w, &obligation.predicate) {
194197
debug!("register_predicate({:?}) -- already seen, skip", obligation);
195198
return;
196199
}
@@ -253,7 +256,9 @@ impl<'tcx> FulfillmentContext<'tcx> {
253256
&self.predicates
254257
}
255258

256-
fn is_duplicate_or_add(&mut self, tcx: &ty::ctxt<'tcx>,
259+
fn is_duplicate_or_add(&mut self,
260+
tcx: &ty::ctxt<'tcx>,
261+
w: RFC1214Warning,
257262
predicate: &ty::Predicate<'tcx>)
258263
-> bool {
259264
// This is a kind of dirty hack to allow us to avoid "rederiving"
@@ -268,10 +273,12 @@ impl<'tcx> FulfillmentContext<'tcx> {
268273
// evaluating the 'nested obligations'. This cache lets us
269274
// skip those.
270275

271-
if self.errors_will_be_reported && predicate.is_global() {
272-
tcx.fulfilled_predicates.borrow_mut().is_duplicate_or_add(predicate)
276+
let will_warn_due_to_rfc1214 = w.0;
277+
let errors_will_be_reported = self.errors_will_be_reported && !will_warn_due_to_rfc1214;
278+
if errors_will_be_reported && predicate.is_global() {
279+
tcx.fulfilled_predicates.borrow_mut().is_duplicate_or_add(w, predicate)
273280
} else {
274-
self.duplicate_set.is_duplicate_or_add(predicate)
281+
self.duplicate_set.is_duplicate_or_add(w, predicate)
275282
}
276283
}
277284

@@ -537,11 +544,13 @@ impl<'tcx> FulfilledPredicates<'tcx> {
537544
}
538545
}
539546

540-
pub fn is_duplicate(&self, p: &ty::Predicate<'tcx>) -> bool {
541-
self.set.contains(p)
547+
pub fn is_duplicate(&self, w: RFC1214Warning, p: &ty::Predicate<'tcx>) -> bool {
548+
let key = (w, p.clone());
549+
self.set.contains(&key)
542550
}
543551

544-
fn is_duplicate_or_add(&mut self, p: &ty::Predicate<'tcx>) -> bool {
545-
!self.set.insert(p.clone())
552+
fn is_duplicate_or_add(&mut self, w: RFC1214Warning, p: &ty::Predicate<'tcx>) -> bool {
553+
let key = (w, p.clone());
554+
!self.set.insert(key)
546555
}
547556
}

src/librustc/middle/traits/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,15 @@ impl<'tcx> ObligationCause<'tcx> {
528528
}
529529
}
530530

531+
/// This marker is used in some caches to record whether the
532+
/// predicate, if it is found to be false, will yield a warning (due
533+
/// to RFC1214) or an error. We separate these two cases in the cache
534+
/// so that if we see the same predicate twice, first resulting in a
535+
/// warning, and next resulting in an error, we still report the
536+
/// error, rather than considering it a duplicate.
537+
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
538+
pub struct RFC1214Warning(bool);
539+
531540
impl<'tcx> ObligationCauseCode<'tcx> {
532541
pub fn is_rfc1214(&self) -> bool {
533542
match *self {

src/librustc/middle/traits/select.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ use super::{ObligationCauseCode, BuiltinDerivedObligation, ImplDerivedObligation
2727
use super::{SelectionError, Unimplemented, OutputTypeParameterMismatch};
2828
use super::{ObjectCastObligation, Obligation};
2929
use super::TraitNotObjectSafe;
30+
use super::RFC1214Warning;
3031
use super::Selection;
3132
use super::SelectionResult;
3233
use super::{VtableBuiltin, VtableImpl, VtableParam, VtableClosure,
@@ -445,7 +446,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
445446
// have been proven elsewhere. This cache only contains
446447
// predicates that are global in scope and hence unaffected by
447448
// the current environment.
448-
if self.tcx().fulfilled_predicates.borrow().is_duplicate(&obligation.predicate) {
449+
let w = RFC1214Warning(false);
450+
if self.tcx().fulfilled_predicates.borrow().is_duplicate(w, &obligation.predicate) {
449451
return EvaluatedToOk;
450452
}
451453

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Test that an RFC1214 warning from an earlier function (`foo`) does
12+
// not suppress an error for the same problem (`WantEq<NotEq>`,
13+
// `NotEq: !Eq`) in a later function (`bar)`. Earlier versions of the
14+
// warning mechanism had an issue due to caching.
15+
16+
#![allow(dead_code)]
17+
#![allow(unused_variables)]
18+
19+
struct WantEq<T:Eq> { t: T }
20+
21+
struct NotEq;
22+
23+
trait Trait<T> { }
24+
25+
fn foo() {
26+
let x: Box<Trait<WantEq<NotEq>>> = loop { };
27+
//~^ WARN E0277
28+
}
29+
30+
fn bar() {
31+
wf::<WantEq<NotEq>>();
32+
//~^ ERROR E0277
33+
}
34+
35+
fn wf<T>() { }
36+
37+
fn main() { }

0 commit comments

Comments
 (0)