diff --git a/src/librustc/traits/auto_trait.rs b/src/librustc/traits/auto_trait.rs index 8239e5ac56e..c3cca149c2c 100644 --- a/src/librustc/traits/auto_trait.rs +++ b/src/librustc/traits/auto_trait.rs @@ -309,7 +309,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { ) -> Option<(ty::ParamEnv<'c>, ty::ParamEnv<'c>)> { let tcx = infcx.tcx; - let mut select = SelectionContext::new(&infcx); + let mut select = SelectionContext::with_negative(&infcx, true); let mut already_visited = FxHashSet::default(); let mut predicates = VecDeque::new(); @@ -338,6 +338,21 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { match &result { &Ok(Some(ref vtable)) => { + // If we see an explicit negative impl (e.g. 'impl !Send for MyStruct'), + // we immediately bail out, since it's impossible for us to continue. + match vtable { + Vtable::VtableImpl(VtableImplData { impl_def_id, .. }) => { + // Blame tidy for the weird bracket placement + if infcx.tcx.impl_polarity(*impl_def_id) == hir::ImplPolarity::Negative + { + debug!("evaluate_nested_obligations: Found explicit negative impl\ + {:?}, bailing out", impl_def_id); + return None; + } + }, + _ => {} + } + let obligations = vtable.clone().nested_obligations().into_iter(); if !self.evaluate_nested_obligations( diff --git a/src/test/rustdoc/issue-55321.rs b/src/test/rustdoc/issue-55321.rs new file mode 100644 index 00000000000..f6ba7c7be17 --- /dev/null +++ b/src/test/rustdoc/issue-55321.rs @@ -0,0 +1,27 @@ +// Copyright 2018 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. + + +#![feature(optin_builtin_traits)] + +// @has issue_55321/struct.A.html +// @has - '//*[@id="implementations-list"]/*[@class="impl"]//*/code' "impl !Send for A" +// @has - '//*[@id="implementations-list"]/*[@class="impl"]//*/code' "impl !Sync for A" +pub struct A(); + +impl !Send for A {} +impl !Sync for A {} + +// @has issue_55321/struct.B.html +// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<T> !Send for \ +// B<T>" +// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]//*/code' "impl<T> !Sync for \ +// B<T>" +pub struct B<T: ?Sized>(A, Box<T>);