Auto merge of #69118 - Dylan-DPC:rollup-7hpm1fj, r=Dylan-DPC
Rollup of 9 pull requests Successful merges: - #67642 (Relax bounds on HashMap/HashSet) - #68848 (Hasten macro parsing) - #69008 (Properly use parent generics for opaque types) - #69048 (Suggestion when encountering assoc types from hrtb) - #69049 (Optimize image sizes) - #69050 (Micro-optimize the heck out of LEB128 reading and writing.) - #69068 (Make the SGX arg cleanup implementation a NOP) - #69082 (When expecting `BoxFuture` and using `async {}`, suggest `Box::pin`) - #69104 (bootstrap: Configure cmake when building sanitizer runtimes) Failed merges: r? @ghost
|
|
@ -262,7 +262,7 @@ impl Step for Llvm {
|
|||
cfg.define("PYTHON_EXECUTABLE", python);
|
||||
}
|
||||
|
||||
configure_cmake(builder, target, &mut cfg);
|
||||
configure_cmake(builder, target, &mut cfg, true);
|
||||
|
||||
// FIXME: we don't actually need to build all LLVM tools and all LLVM
|
||||
// libraries here, e.g., we just want a few components and a few
|
||||
|
|
@ -301,7 +301,12 @@ fn check_llvm_version(builder: &Builder<'_>, llvm_config: &Path) {
|
|||
panic!("\n\nbad LLVM version: {}, need >=7.0\n\n", version)
|
||||
}
|
||||
|
||||
fn configure_cmake(builder: &Builder<'_>, target: Interned<String>, cfg: &mut cmake::Config) {
|
||||
fn configure_cmake(
|
||||
builder: &Builder<'_>,
|
||||
target: Interned<String>,
|
||||
cfg: &mut cmake::Config,
|
||||
use_compiler_launcher: bool,
|
||||
) {
|
||||
// Do not print installation messages for up-to-date files.
|
||||
// LLVM and LLD builds can produce a lot of those and hit CI limits on log size.
|
||||
cfg.define("CMAKE_INSTALL_MESSAGE", "LAZY");
|
||||
|
|
@ -372,9 +377,11 @@ fn configure_cmake(builder: &Builder<'_>, target: Interned<String>, cfg: &mut cm
|
|||
} else {
|
||||
// If ccache is configured we inform the build a little differently how
|
||||
// to invoke ccache while also invoking our compilers.
|
||||
if let Some(ref ccache) = builder.config.ccache {
|
||||
cfg.define("CMAKE_C_COMPILER_LAUNCHER", ccache)
|
||||
.define("CMAKE_CXX_COMPILER_LAUNCHER", ccache);
|
||||
if use_compiler_launcher {
|
||||
if let Some(ref ccache) = builder.config.ccache {
|
||||
cfg.define("CMAKE_C_COMPILER_LAUNCHER", ccache)
|
||||
.define("CMAKE_CXX_COMPILER_LAUNCHER", ccache);
|
||||
}
|
||||
}
|
||||
cfg.define("CMAKE_C_COMPILER", sanitize_cc(cc))
|
||||
.define("CMAKE_CXX_COMPILER", sanitize_cc(cxx));
|
||||
|
|
@ -458,7 +465,7 @@ impl Step for Lld {
|
|||
t!(fs::create_dir_all(&out_dir));
|
||||
|
||||
let mut cfg = cmake::Config::new(builder.src.join("src/llvm-project/lld"));
|
||||
configure_cmake(builder, target, &mut cfg);
|
||||
configure_cmake(builder, target, &mut cfg, true);
|
||||
|
||||
// This is an awful, awful hack. Discovered when we migrated to using
|
||||
// clang-cl to compile LLVM/LLD it turns out that LLD, when built out of
|
||||
|
|
@ -595,10 +602,7 @@ impl Step for Sanitizers {
|
|||
let _time = util::timeit(&builder);
|
||||
|
||||
let mut cfg = cmake::Config::new(&compiler_rt_dir);
|
||||
cfg.target(&self.target);
|
||||
cfg.host(&builder.config.build);
|
||||
cfg.profile("Release");
|
||||
|
||||
cfg.define("CMAKE_C_COMPILER_TARGET", self.target);
|
||||
cfg.define("COMPILER_RT_BUILD_BUILTINS", "OFF");
|
||||
cfg.define("COMPILER_RT_BUILD_CRT", "OFF");
|
||||
|
|
@ -610,6 +614,12 @@ impl Step for Sanitizers {
|
|||
cfg.define("COMPILER_RT_USE_LIBCXX", "OFF");
|
||||
cfg.define("LLVM_CONFIG_PATH", &llvm_config);
|
||||
|
||||
// On Darwin targets the sanitizer runtimes are build as universal binaries.
|
||||
// Unfortunately sccache currently lacks support to build them successfully.
|
||||
// Disable compiler launcher on Darwin targets to avoid potential issues.
|
||||
let use_compiler_launcher = !self.target.contains("apple-darwin");
|
||||
configure_cmake(builder, self.target, &mut cfg, use_compiler_launcher);
|
||||
|
||||
t!(fs::create_dir_all(&out_dir));
|
||||
cfg.out_dir(out_dir);
|
||||
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 3.8 KiB |
|
|
@ -727,6 +727,10 @@ unsafe impl<T: ?Sized> Freeze for &mut T {}
|
|||
/// [`Pin<P>`]: ../pin/struct.Pin.html
|
||||
/// [`pin module`]: ../../std/pin/index.html
|
||||
#[stable(feature = "pin", since = "1.33.0")]
|
||||
#[rustc_on_unimplemented(
|
||||
on(_Self = "std::future::Future", note = "consider using `Box::pin`",),
|
||||
message = "`{Self}` cannot be unpinned"
|
||||
)]
|
||||
#[lang = "unpin"]
|
||||
pub auto trait Unpin {}
|
||||
|
||||
|
|
|
|||
|
|
@ -201,6 +201,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
if let ty::Dynamic(traits, _) = self_ty.kind {
|
||||
for t in *traits.skip_binder() {
|
||||
match t {
|
||||
ty::ExistentialPredicate::Trait(trait_ref) => {
|
||||
flags.push((sym::_Self, Some(self.tcx.def_path_str(trait_ref.def_id))))
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(Some(command)) =
|
||||
OnUnimplementedDirective::of_item(self.tcx, trait_ref.def_id, def_id)
|
||||
|
|
|
|||
|
|
@ -701,10 +701,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
|||
})
|
||||
.collect::<Vec<_>>();
|
||||
// Add the suggestion for the return type.
|
||||
suggestions.push((
|
||||
ret_ty.span,
|
||||
format!("Box<{}{}>", if has_dyn { "" } else { "dyn " }, snippet),
|
||||
));
|
||||
suggestions.push((ret_ty.span, format!("Box<dyn {}>", trait_obj)));
|
||||
err.multipart_suggestion(
|
||||
"return a boxed trait object instead",
|
||||
suggestions,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
#![feature(cow_is_borrowed)]
|
||||
#![feature(crate_visibility_modifier)]
|
||||
#![feature(decl_macro)]
|
||||
#![feature(proc_macro_diagnostic)]
|
||||
|
|
|
|||
|
|
@ -78,13 +78,11 @@ use crate::mbe::{self, TokenTree};
|
|||
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_parse::parser::{FollowedByType, Parser, PathStyle};
|
||||
use rustc_parse::Directory;
|
||||
use rustc_session::parse::ParseSess;
|
||||
use rustc_span::symbol::{kw, sym, Symbol};
|
||||
use syntax::ast::{Ident, Name};
|
||||
use syntax::ptr::P;
|
||||
use syntax::token::{self, DocComment, Nonterminal, Token};
|
||||
use syntax::tokenstream::TokenStream;
|
||||
|
||||
use rustc_errors::{FatalError, PResult};
|
||||
use rustc_span::Span;
|
||||
|
|
@ -92,6 +90,7 @@ use smallvec::{smallvec, SmallVec};
|
|||
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use std::borrow::Cow;
|
||||
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
||||
use std::mem;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
|
@ -613,28 +612,9 @@ fn inner_parse_loop<'root, 'tt>(
|
|||
Success(())
|
||||
}
|
||||
|
||||
/// Use the given sequence of token trees (`ms`) as a matcher. Match the given token stream `tts`
|
||||
/// against it and return the match.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// - `sess`: The session into which errors are emitted
|
||||
/// - `tts`: The tokenstream we are matching against the pattern `ms`
|
||||
/// - `ms`: A sequence of token trees representing a pattern against which we are matching
|
||||
/// - `directory`: Information about the file locations (needed for the black-box parser)
|
||||
/// - `recurse_into_modules`: Whether or not to recurse into modules (needed for the black-box
|
||||
/// parser)
|
||||
pub(super) fn parse(
|
||||
sess: &ParseSess,
|
||||
tts: TokenStream,
|
||||
ms: &[TokenTree],
|
||||
directory: Option<Directory<'_>>,
|
||||
recurse_into_modules: bool,
|
||||
) -> NamedParseResult {
|
||||
// Create a parser that can be used for the "black box" parts.
|
||||
let mut parser =
|
||||
Parser::new(sess, tts, directory, recurse_into_modules, true, rustc_parse::MACRO_ARGUMENTS);
|
||||
|
||||
/// Use the given sequence of token trees (`ms`) as a matcher. Match the token
|
||||
/// stream from the given `parser` against it and return the match.
|
||||
pub(super) fn parse_tt(parser: &mut Cow<'_, Parser<'_>>, ms: &[TokenTree]) -> NamedParseResult {
|
||||
// A queue of possible matcher positions. We initialize it with the matcher position in which
|
||||
// the "dot" is before the first token of the first token tree in `ms`. `inner_parse_loop` then
|
||||
// processes all of these possible matcher positions and produces possible next positions into
|
||||
|
|
@ -659,7 +639,7 @@ pub(super) fn parse(
|
|||
// parsing from the black-box parser done. The result is that `next_items` will contain a
|
||||
// bunch of possible next matcher positions in `next_items`.
|
||||
match inner_parse_loop(
|
||||
sess,
|
||||
parser.sess,
|
||||
&mut cur_items,
|
||||
&mut next_items,
|
||||
&mut eof_items,
|
||||
|
|
@ -684,7 +664,7 @@ pub(super) fn parse(
|
|||
if eof_items.len() == 1 {
|
||||
let matches =
|
||||
eof_items[0].matches.iter_mut().map(|dv| Lrc::make_mut(dv).pop().unwrap());
|
||||
return nameize(sess, ms, matches);
|
||||
return nameize(parser.sess, ms, matches);
|
||||
} else if eof_items.len() > 1 {
|
||||
return Error(
|
||||
parser.token.span,
|
||||
|
|
@ -709,9 +689,14 @@ pub(super) fn parse(
|
|||
// unnecessary implicit clone later in Rc::make_mut.
|
||||
drop(eof_items);
|
||||
|
||||
// If there are no possible next positions AND we aren't waiting for the black-box parser,
|
||||
// then there is a syntax error.
|
||||
if bb_items.is_empty() && next_items.is_empty() {
|
||||
return Failure(parser.token.clone(), "no rules expected this token in macro call");
|
||||
}
|
||||
// Another possibility is that we need to call out to parse some rust nonterminal
|
||||
// (black-box) parser. However, if there is not EXACTLY ONE of these, something is wrong.
|
||||
if (!bb_items.is_empty() && !next_items.is_empty()) || bb_items.len() > 1 {
|
||||
else if (!bb_items.is_empty() && !next_items.is_empty()) || bb_items.len() > 1 {
|
||||
let nts = bb_items
|
||||
.iter()
|
||||
.map(|item| match item.top_elts.get_tt(item.idx) {
|
||||
|
|
@ -733,16 +718,11 @@ pub(super) fn parse(
|
|||
),
|
||||
);
|
||||
}
|
||||
// If there are no possible next positions AND we aren't waiting for the black-box parser,
|
||||
// then there is a syntax error.
|
||||
else if bb_items.is_empty() && next_items.is_empty() {
|
||||
return Failure(parser.token.take(), "no rules expected this token in macro call");
|
||||
}
|
||||
// Dump all possible `next_items` into `cur_items` for the next iteration.
|
||||
else if !next_items.is_empty() {
|
||||
// Now process the next token
|
||||
cur_items.extend(next_items.drain(..));
|
||||
parser.bump();
|
||||
parser.to_mut().bump();
|
||||
}
|
||||
// Finally, we have the case where we need to call the black-box parser to get some
|
||||
// nonterminal.
|
||||
|
|
@ -754,7 +734,7 @@ pub(super) fn parse(
|
|||
let match_cur = item.match_cur;
|
||||
item.push_match(
|
||||
match_cur,
|
||||
MatchedNonterminal(Lrc::new(parse_nt(&mut parser, span, ident.name))),
|
||||
MatchedNonterminal(Lrc::new(parse_nt(parser.to_mut(), span, ident.name))),
|
||||
);
|
||||
item.idx += 1;
|
||||
item.match_cur += 1;
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
use crate::base::{DummyResult, ExtCtxt, MacResult, TTMacroExpander};
|
||||
use crate::base::{DummyResult, ExpansionData, ExtCtxt, MacResult, TTMacroExpander};
|
||||
use crate::base::{SyntaxExtension, SyntaxExtensionKind};
|
||||
use crate::expand::{ensure_complete_parse, parse_ast_fragment, AstFragment, AstFragmentKind};
|
||||
use crate::mbe;
|
||||
use crate::mbe::macro_check;
|
||||
use crate::mbe::macro_parser::parse;
|
||||
use crate::mbe::macro_parser::parse_tt;
|
||||
use crate::mbe::macro_parser::{Error, Failure, Success};
|
||||
use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, NamedParseResult};
|
||||
use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq};
|
||||
use crate::mbe::transcribe::transcribe;
|
||||
|
||||
use rustc_ast_pretty::pprust;
|
||||
|
|
@ -166,9 +166,9 @@ impl TTMacroExpander for MacroRulesMacroExpander {
|
|||
}
|
||||
}
|
||||
|
||||
fn trace_macros_note(cx: &mut ExtCtxt<'_>, sp: Span, message: String) {
|
||||
fn trace_macros_note(cx_expansions: &mut FxHashMap<Span, Vec<String>>, sp: Span, message: String) {
|
||||
let sp = sp.macro_backtrace().last().map(|trace| trace.call_site).unwrap_or(sp);
|
||||
cx.expansions.entry(sp).or_default().push(message);
|
||||
cx_expansions.entry(sp).or_default().push(message);
|
||||
}
|
||||
|
||||
/// Given `lhses` and `rhses`, this is the new macro we create
|
||||
|
|
@ -184,12 +184,36 @@ fn generic_extension<'cx>(
|
|||
) -> Box<dyn MacResult + 'cx> {
|
||||
if cx.trace_macros() {
|
||||
let msg = format!("expanding `{}! {{ {} }}`", name, pprust::tts_to_string(arg.clone()));
|
||||
trace_macros_note(cx, sp, msg);
|
||||
trace_macros_note(&mut cx.expansions, sp, msg);
|
||||
}
|
||||
|
||||
// Which arm's failure should we report? (the one furthest along)
|
||||
let mut best_failure: Option<(Token, &str)> = None;
|
||||
|
||||
// We create a base parser that can be used for the "black box" parts.
|
||||
// Every iteration needs a fresh copy of that base parser. However, the
|
||||
// parser is not mutated on many of the iterations, particularly when
|
||||
// dealing with macros like this:
|
||||
//
|
||||
// macro_rules! foo {
|
||||
// ("a") => (A);
|
||||
// ("b") => (B);
|
||||
// ("c") => (C);
|
||||
// // ... etc. (maybe hundreds more)
|
||||
// }
|
||||
//
|
||||
// as seen in the `html5ever` benchmark. We use a `Cow` so that the base
|
||||
// parser is only cloned when necessary (upon mutation). Furthermore, we
|
||||
// reinitialize the `Cow` with the base parser at the start of every
|
||||
// iteration, so that any mutated parsers are not reused. This is all quite
|
||||
// hacky, but speeds up the `html5ever` benchmark significantly. (Issue
|
||||
// 68836 suggests a more comprehensive but more complex change to deal with
|
||||
// this situation.)
|
||||
let base_parser = base_parser_from_cx(&cx.current_expansion, &cx.parse_sess, arg.clone());
|
||||
|
||||
for (i, lhs) in lhses.iter().enumerate() {
|
||||
let mut parser = Cow::Borrowed(&base_parser);
|
||||
|
||||
// try each arm's matchers
|
||||
let lhs_tt = match *lhs {
|
||||
mbe::TokenTree::Delimited(_, ref delim) => &delim.tts[..],
|
||||
|
|
@ -202,7 +226,7 @@ fn generic_extension<'cx>(
|
|||
// are not recorded. On the first `Success(..)`ful matcher, the spans are merged.
|
||||
let mut gated_spans_snaphot = mem::take(&mut *cx.parse_sess.gated_spans.spans.borrow_mut());
|
||||
|
||||
match parse_tt(cx, lhs_tt, arg.clone()) {
|
||||
match parse_tt(&mut parser, lhs_tt) {
|
||||
Success(named_matches) => {
|
||||
// The matcher was `Success(..)`ful.
|
||||
// Merge the gated spans from parsing the matcher with the pre-existing ones.
|
||||
|
|
@ -232,11 +256,11 @@ fn generic_extension<'cx>(
|
|||
|
||||
if cx.trace_macros() {
|
||||
let msg = format!("to `{}`", pprust::tts_to_string(tts.clone()));
|
||||
trace_macros_note(cx, sp, msg);
|
||||
trace_macros_note(&mut cx.expansions, sp, msg);
|
||||
}
|
||||
|
||||
let directory = Directory {
|
||||
path: Cow::from(cx.current_expansion.module.directory.as_path()),
|
||||
path: cx.current_expansion.module.directory.clone(),
|
||||
ownership: cx.current_expansion.directory_ownership,
|
||||
};
|
||||
let mut p = Parser::new(cx.parse_sess(), tts, Some(directory), true, false, None);
|
||||
|
|
@ -269,6 +293,7 @@ fn generic_extension<'cx>(
|
|||
// Restore to the state before snapshotting and maybe try again.
|
||||
mem::swap(&mut gated_spans_snaphot, &mut cx.parse_sess.gated_spans.spans.borrow_mut());
|
||||
}
|
||||
drop(base_parser);
|
||||
|
||||
let (token, label) = best_failure.expect("ran no matchers");
|
||||
let span = token.span.substitute_dummy(sp);
|
||||
|
|
@ -286,7 +311,9 @@ fn generic_extension<'cx>(
|
|||
mbe::TokenTree::Delimited(_, ref delim) => &delim.tts[..],
|
||||
_ => continue,
|
||||
};
|
||||
match parse_tt(cx, lhs_tt, arg.clone()) {
|
||||
let base_parser =
|
||||
base_parser_from_cx(&cx.current_expansion, &cx.parse_sess, arg.clone());
|
||||
match parse_tt(&mut Cow::Borrowed(&base_parser), lhs_tt) {
|
||||
Success(_) => {
|
||||
if comma_span.is_dummy() {
|
||||
err.note("you might be missing a comma");
|
||||
|
|
@ -368,7 +395,8 @@ pub fn compile_declarative_macro(
|
|||
),
|
||||
];
|
||||
|
||||
let argument_map = match parse(sess, body, &argument_gram, None, true) {
|
||||
let base_parser = Parser::new(sess, body, None, true, true, rustc_parse::MACRO_ARGUMENTS);
|
||||
let argument_map = match parse_tt(&mut Cow::Borrowed(&base_parser), &argument_gram) {
|
||||
Success(m) => m,
|
||||
Failure(token, msg) => {
|
||||
let s = parse_failure_msg(&token);
|
||||
|
|
@ -1184,14 +1212,16 @@ fn quoted_tt_to_string(tt: &mbe::TokenTree) -> String {
|
|||
}
|
||||
}
|
||||
|
||||
/// Use this token tree as a matcher to parse given tts.
|
||||
fn parse_tt(cx: &ExtCtxt<'_>, mtch: &[mbe::TokenTree], tts: TokenStream) -> NamedParseResult {
|
||||
// `None` is because we're not interpolating
|
||||
fn base_parser_from_cx<'cx>(
|
||||
current_expansion: &'cx ExpansionData,
|
||||
sess: &'cx ParseSess,
|
||||
tts: TokenStream,
|
||||
) -> Parser<'cx> {
|
||||
let directory = Directory {
|
||||
path: Cow::from(cx.current_expansion.module.directory.as_path()),
|
||||
ownership: cx.current_expansion.directory_ownership,
|
||||
path: current_expansion.module.directory.clone(),
|
||||
ownership: current_expansion.directory_ownership,
|
||||
};
|
||||
parse(cx.parse_sess(), tts, mtch, Some(directory), true)
|
||||
Parser::new(sess, tts, Some(directory), true, true, rustc_parse::MACRO_ARGUMENTS)
|
||||
}
|
||||
|
||||
/// Generates an appropriate parsing failure message. For EOF, this is "unexpected end...". For
|
||||
|
|
|
|||
|
|
@ -12,8 +12,7 @@ use syntax::ast;
|
|||
use syntax::token::{self, Nonterminal};
|
||||
use syntax::tokenstream::{self, TokenStream, TokenTree};
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::path::Path;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::str;
|
||||
|
||||
use log::info;
|
||||
|
|
@ -29,8 +28,8 @@ pub mod validate_attr;
|
|||
pub mod config;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Directory<'a> {
|
||||
pub path: Cow<'a, Path>,
|
||||
pub struct Directory {
|
||||
pub path: PathBuf,
|
||||
pub ownership: DirectoryOwnership,
|
||||
}
|
||||
|
||||
|
|
@ -274,7 +273,7 @@ pub fn stream_to_parser<'a>(
|
|||
pub fn stream_to_parser_with_base_dir<'a>(
|
||||
sess: &'a ParseSess,
|
||||
stream: TokenStream,
|
||||
base_dir: Directory<'a>,
|
||||
base_dir: Directory,
|
||||
) -> Parser<'a> {
|
||||
Parser::new(sess, stream, Some(base_dir), true, false, None)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ use syntax::token::{self, DelimToken, Token, TokenKind};
|
|||
use syntax::tokenstream::{self, DelimSpan, TokenStream, TokenTree, TreeAndJoint};
|
||||
use syntax::util::comments::{doc_comment_style, strip_doc_comment_decoration};
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::path::PathBuf;
|
||||
use std::{cmp, mem, slice};
|
||||
|
||||
|
|
@ -108,7 +107,7 @@ pub struct Parser<'a> {
|
|||
pub prev_span: Span,
|
||||
restrictions: Restrictions,
|
||||
/// Used to determine the path to externally loaded source files.
|
||||
pub(super) directory: Directory<'a>,
|
||||
pub(super) directory: Directory,
|
||||
/// `true` to parse sub-modules in other files.
|
||||
// Public for rustfmt usage.
|
||||
pub recurse_into_file_modules: bool,
|
||||
|
|
@ -370,7 +369,7 @@ impl<'a> Parser<'a> {
|
|||
pub fn new(
|
||||
sess: &'a ParseSess,
|
||||
tokens: TokenStream,
|
||||
directory: Option<Directory<'a>>,
|
||||
directory: Option<Directory>,
|
||||
recurse_into_file_modules: bool,
|
||||
desugar_doc_comments: bool,
|
||||
subparser_name: Option<&'static str>,
|
||||
|
|
@ -385,7 +384,7 @@ impl<'a> Parser<'a> {
|
|||
restrictions: Restrictions::empty(),
|
||||
recurse_into_file_modules,
|
||||
directory: Directory {
|
||||
path: Cow::from(PathBuf::new()),
|
||||
path: PathBuf::new(),
|
||||
ownership: DirectoryOwnership::Owned { relative: None },
|
||||
},
|
||||
root_module_name: None,
|
||||
|
|
@ -413,7 +412,7 @@ impl<'a> Parser<'a> {
|
|||
&sess.source_map().lookup_char_pos(parser.token.span.lo()).file.unmapped_path
|
||||
{
|
||||
if let Some(directory_path) = path.parent() {
|
||||
parser.directory.path = Cow::from(directory_path.to_path_buf());
|
||||
parser.directory.path = directory_path.to_path_buf();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -285,7 +285,7 @@ impl<'a> Parser<'a> {
|
|||
|
||||
fn push_directory(&mut self, id: Ident, attrs: &[Attribute]) {
|
||||
if let Some(path) = attr::first_attr_value_str_by_name(attrs, sym::path) {
|
||||
self.directory.path.to_mut().push(&*path.as_str());
|
||||
self.directory.path.push(&*path.as_str());
|
||||
self.directory.ownership = DirectoryOwnership::Owned { relative: None };
|
||||
} else {
|
||||
// We have to push on the current module name in the case of relative
|
||||
|
|
@ -297,10 +297,10 @@ impl<'a> Parser<'a> {
|
|||
if let DirectoryOwnership::Owned { relative } = &mut self.directory.ownership {
|
||||
if let Some(ident) = relative.take() {
|
||||
// remove the relative offset
|
||||
self.directory.path.to_mut().push(&*ident.as_str());
|
||||
self.directory.path.push(&*ident.as_str());
|
||||
}
|
||||
}
|
||||
self.directory.path.to_mut().push(&*id.as_str());
|
||||
self.directory.path.push(&*id.as_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
self.annotate_expected_due_to_let_ty(err, expr);
|
||||
self.suggest_compatible_variants(err, expr, expected, expr_ty);
|
||||
self.suggest_ref_or_into(err, expr, expected, expr_ty);
|
||||
if self.suggest_calling_boxed_future_when_appropriate(err, expr, expected, expr_ty) {
|
||||
return;
|
||||
}
|
||||
self.suggest_boxing_when_appropriate(err, expr, expected, expr_ty);
|
||||
self.suggest_missing_await(err, expr, expected, expr_ty);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5038,14 +5038,60 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
Applicability::MachineApplicable,
|
||||
);
|
||||
err.note(
|
||||
"for more on the distinction between the stack and the \
|
||||
heap, read https://doc.rust-lang.org/book/ch15-01-box.html, \
|
||||
https://doc.rust-lang.org/rust-by-example/std/box.html, and \
|
||||
https://doc.rust-lang.org/std/boxed/index.html",
|
||||
"for more on the distinction between the stack and the heap, read \
|
||||
https://doc.rust-lang.org/book/ch15-01-box.html, \
|
||||
https://doc.rust-lang.org/rust-by-example/std/box.html, and \
|
||||
https://doc.rust-lang.org/std/boxed/index.html",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// When encountering an `impl Future` where `BoxFuture` is expected, suggest `Box::pin`.
|
||||
fn suggest_calling_boxed_future_when_appropriate(
|
||||
&self,
|
||||
err: &mut DiagnosticBuilder<'_>,
|
||||
expr: &hir::Expr<'_>,
|
||||
expected: Ty<'tcx>,
|
||||
found: Ty<'tcx>,
|
||||
) -> bool {
|
||||
// Handle #68197.
|
||||
|
||||
if self.tcx.hir().is_const_context(expr.hir_id) {
|
||||
// Do not suggest `Box::new` in const context.
|
||||
return false;
|
||||
}
|
||||
let pin_did = self.tcx.lang_items().pin_type();
|
||||
match expected.kind {
|
||||
ty::Adt(def, _) if Some(def.did) != pin_did => return false,
|
||||
// This guards the `unwrap` and `mk_box` below.
|
||||
_ if pin_did.is_none() || self.tcx.lang_items().owned_box().is_none() => return false,
|
||||
_ => {}
|
||||
}
|
||||
let boxed_found = self.tcx.mk_box(found);
|
||||
let new_found = self.tcx.mk_lang_item(boxed_found, lang_items::PinTypeLangItem).unwrap();
|
||||
if let (true, Ok(snippet)) = (
|
||||
self.can_coerce(new_found, expected),
|
||||
self.sess().source_map().span_to_snippet(expr.span),
|
||||
) {
|
||||
match found.kind {
|
||||
ty::Adt(def, _) if def.is_box() => {
|
||||
err.help("use `Box::pin`");
|
||||
}
|
||||
_ => {
|
||||
err.span_suggestion(
|
||||
expr.span,
|
||||
"you need to pin and box this expression",
|
||||
format!("Box::pin({})", snippet),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
}
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// A common error is to forget to add a semicolon at the end of a block, e.g.,
|
||||
///
|
||||
/// ```
|
||||
|
|
|
|||
|
|
@ -278,6 +278,17 @@ impl ItemCtxt<'tcx> {
|
|||
pub fn to_ty(&self, ast_ty: &'tcx hir::Ty<'tcx>) -> Ty<'tcx> {
|
||||
AstConv::ast_ty_to_ty(self, ast_ty)
|
||||
}
|
||||
|
||||
pub fn hir_id(&self) -> hir::HirId {
|
||||
self.tcx
|
||||
.hir()
|
||||
.as_local_hir_id(self.item_def_id)
|
||||
.expect("Non-local call to local provider is_const_fn")
|
||||
}
|
||||
|
||||
pub fn node(&self) -> hir::Node<'tcx> {
|
||||
self.tcx.hir().get(self.hir_id())
|
||||
}
|
||||
}
|
||||
|
||||
impl AstConv<'tcx> for ItemCtxt<'tcx> {
|
||||
|
|
@ -290,15 +301,7 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> {
|
|||
}
|
||||
|
||||
fn default_constness_for_trait_bounds(&self) -> ast::Constness {
|
||||
// FIXME: refactor this into a method
|
||||
let hir_id = self
|
||||
.tcx
|
||||
.hir()
|
||||
.as_local_hir_id(self.item_def_id)
|
||||
.expect("Non-local call to local provider is_const_fn");
|
||||
|
||||
let node = self.tcx.hir().get(hir_id);
|
||||
if let Some(fn_like) = FnLikeNode::from_node(node) {
|
||||
if let Some(fn_like) = FnLikeNode::from_node(self.node()) {
|
||||
fn_like.constness()
|
||||
} else {
|
||||
ast::Constness::NotConst
|
||||
|
|
@ -352,14 +355,80 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> {
|
|||
self.tcx().mk_projection(item_def_id, item_substs)
|
||||
} else {
|
||||
// There are no late-bound regions; we can just ignore the binder.
|
||||
struct_span_err!(
|
||||
let mut err = struct_span_err!(
|
||||
self.tcx().sess,
|
||||
span,
|
||||
E0212,
|
||||
"cannot extract an associated type from a higher-ranked trait bound \
|
||||
in this context"
|
||||
)
|
||||
.emit();
|
||||
);
|
||||
|
||||
match self.node() {
|
||||
hir::Node::Field(_) | hir::Node::Ctor(_) | hir::Node::Variant(_) => {
|
||||
let item =
|
||||
self.tcx.hir().expect_item(self.tcx.hir().get_parent_item(self.hir_id()));
|
||||
match &item.kind {
|
||||
hir::ItemKind::Enum(_, generics)
|
||||
| hir::ItemKind::Struct(_, generics)
|
||||
| hir::ItemKind::Union(_, generics) => {
|
||||
// FIXME: look for an appropriate lt name if `'a` is already used
|
||||
let (lt_sp, sugg) = match &generics.params[..] {
|
||||
[] => (generics.span, "<'a>".to_string()),
|
||||
[bound, ..] => (bound.span.shrink_to_lo(), "'a, ".to_string()),
|
||||
};
|
||||
let suggestions = vec![
|
||||
(lt_sp, sugg),
|
||||
(
|
||||
span,
|
||||
format!(
|
||||
"{}::{}",
|
||||
// Replace the existing lifetimes with a new named lifetime.
|
||||
self.tcx
|
||||
.replace_late_bound_regions(&poly_trait_ref, |_| {
|
||||
self.tcx.mk_region(ty::ReEarlyBound(
|
||||
ty::EarlyBoundRegion {
|
||||
def_id: item_def_id,
|
||||
index: 0,
|
||||
name: Symbol::intern("'a"),
|
||||
},
|
||||
))
|
||||
})
|
||||
.0,
|
||||
item_segment.ident
|
||||
),
|
||||
),
|
||||
];
|
||||
err.multipart_suggestion(
|
||||
"use a fully qualified path with explicit lifetimes",
|
||||
suggestions,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
hir::Node::Item(hir::Item { kind: hir::ItemKind::Struct(..), .. })
|
||||
| hir::Node::Item(hir::Item { kind: hir::ItemKind::Enum(..), .. })
|
||||
| hir::Node::Item(hir::Item { kind: hir::ItemKind::Union(..), .. }) => {}
|
||||
hir::Node::Item(_)
|
||||
| hir::Node::ForeignItem(_)
|
||||
| hir::Node::TraitItem(_)
|
||||
| hir::Node::ImplItem(_) => {
|
||||
err.span_suggestion(
|
||||
span,
|
||||
"use a fully qualified path with inferred lifetimes",
|
||||
format!(
|
||||
"{}::{}",
|
||||
// Erase named lt, we want `<A as B<'_>::C`, not `<A as B<'a>::C`.
|
||||
self.tcx.anonymize_late_bound_regions(&poly_trait_ref).skip_binder(),
|
||||
item_segment.ident
|
||||
),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
err.emit();
|
||||
self.tcx().types.err
|
||||
}
|
||||
}
|
||||
|
|
@ -1054,7 +1123,27 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics {
|
|||
Some(tcx.closure_base_def_id(def_id))
|
||||
}
|
||||
Node::Item(item) => match item.kind {
|
||||
ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn, .. }) => impl_trait_fn,
|
||||
ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn, .. }) => {
|
||||
impl_trait_fn.or_else(|| {
|
||||
let parent_id = tcx.hir().get_parent_item(hir_id);
|
||||
if parent_id != hir_id && parent_id != CRATE_HIR_ID {
|
||||
debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent_id);
|
||||
// If this 'impl Trait' is nested inside another 'impl Trait'
|
||||
// (e.g. `impl Foo<MyType = impl Bar<A>>`), we need to use the 'parent'
|
||||
// 'impl Trait' for its generic parameters, since we can reference them
|
||||
// from the 'child' 'impl Trait'
|
||||
if let Node::Item(hir::Item { kind: ItemKind::OpaqueTy(..), .. }) =
|
||||
tcx.hir().get(parent_id)
|
||||
{
|
||||
Some(tcx.hir().local_def_id(parent_id))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
<?xml version="1.0" ?><svg height="1792" viewBox="0 0 1792 1792" width="1792" xmlns="http://www.w3.org/2000/svg"><path d="M1615 0q70 0 122.5 46.5t52.5 116.5q0 63-45 151-332 629-465 752-97 91-218 91-126 0-216.5-92.5t-90.5-219.5q0-128 92-212l638-579q59-54 130-54zm-909 1034q39 76 106.5 130t150.5 76l1 71q4 213-129.5 347t-348.5 134q-123 0-218-46.5t-152.5-127.5-86.5-183-29-220q7 5 41 30t62 44.5 59 36.5 46 17q41 0 55-37 25-66 57.5-112.5t69.5-76 88-47.5 103-25.5 125-10.5z"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1792" height="1792" viewBox="0 0 1792 1792"><path d="M1615 0q70 0 122.5 46.5t52.5 116.5q0 63-45 151-332 629-465 752-97 91-218 91-126 0-216.5-92.5t-90.5-219.5q0-128 92-212l638-579q59-54 130-54zm-909 1034q39 76 106.5 130t150.5 76l1 71q4 213-129.5 347t-348.5 134q-123 0-218-46.5t-152.5-127.5-86.5-183-29-220q7 5 41 30t62 44.5 59 36.5 46 17q41 0 55-37 25-66 57.5-112.5t69.5-76 88-47.5 103-25.5 125-10.5z"/></svg>
|
||||
|
Before Width: | Height: | Size: 477 B After Width: | Height: | Size: 455 B |
|
|
@ -1 +1 @@
|
|||
<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'><svg height="128px" id="Layer_1" style="enable-background:new 0 0 128 128;" version="1.1" viewBox="-30 -20 176 176" width="128px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g><line style="fill:none;stroke:#2F3435;stroke-width:12;stroke-linecap:square;stroke-miterlimit:10;" x1="111" x2="64" y1="40.5" y2="87.499"/><line style="fill:none;stroke:#2F3435;stroke-width:12;stroke-linecap:square;stroke-miterlimit:10;" x1="64" x2="17" y1="87.499" y2="40.5"/></g></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="Layer_1" width="128" height="128" enable-background="new 0 0 128 128" version="1.1" viewBox="-30 -20 176 176" xml:space="preserve"><g><line x1="111" x2="64" y1="40.5" y2="87.499" fill="none" stroke="#2F3435" stroke-linecap="square" stroke-miterlimit="10" stroke-width="12"/><line x1="64" x2="17" y1="87.499" y2="40.5" fill="none" stroke="#2F3435" stroke-linecap="square" stroke-miterlimit="10" stroke-width="12"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 641 B After Width: | Height: | Size: 510 B |
|
|
@ -1 +1 @@
|
|||
<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'><svg enable-background="new 0 0 27.434 29.5" height="29.5px" id="Capa_1" version="1.1" viewBox="0 0 27.434 29.5" width="27.434px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g><path d="M27.315,18.389c-0.165-0.604-0.509-1.113-0.981-1.459c-0.042-0.144-0.083-0.429-0.015-0.761l0.037-0.177v-0.182V14.8 c0-1.247-0.006-1.277-0.048-1.472c-0.076-0.354-0.035-0.653,0.007-0.803c0.477-0.346,0.828-0.861,0.996-1.476 c0.261-0.956,0.076-2.091-0.508-3.114l-0.591-1.032c-0.746-1.307-1.965-2.119-3.182-2.119c-0.378,0-0.75,0.081-1.085,0.235 c-0.198-0.025-0.554-0.15-0.855-0.389l-0.103-0.082l-0.114-0.065l-1.857-1.067L18.92,3.36l-0.105-0.044 c-0.376-0.154-0.658-0.41-0.768-0.556C17.918,1.172,16.349,0,14.296,0H13.14c-2.043,0-3.608,1.154-3.749,2.721 C9.277,2.862,8.999,3.104,8.633,3.25l-0.1,0.039L8.439,3.341L6.495,4.406L6.363,4.479L6.245,4.573 C5.936,4.82,5.596,4.944,5.416,4.977c-0.314-0.139-0.66-0.21-1.011-0.21c-1.198,0-2.411,0.819-3.165,2.139L0.65,7.938 c-0.412,0.72-0.642,1.521-0.644,2.258c-0.003,0.952,0.362,1.756,1.013,2.256c0.034,0.155,0.061,0.448-0.016,0.786 c-0.038,0.168-0.062,0.28-0.062,1.563c0,1.148,0,1.148,0.015,1.262l0.009,0.073l0.017,0.073c0.073,0.346,0.045,0.643,0.011,0.802 C0.348,17.512-0.01,18.314,0,19.268c0.008,0.729,0.238,1.523,0.648,2.242l0.589,1.031c0.761,1.331,1.967,2.159,3.15,2.159 c0.324,0,0.645-0.064,0.938-0.187c0.167,0.038,0.492,0.156,0.813,0.416l0.11,0.088l0.124,0.07l2.045,1.156l0.102,0.057l0.107,0.043 c0.364,0.147,0.646,0.381,0.766,0.521c0.164,1.52,1.719,2.634,3.745,2.634h1.155c2.037,0,3.598-1.134,3.747-2.675 c0.117-0.145,0.401-0.393,0.774-0.549l0.111-0.047l0.105-0.062l1.96-1.159l0.105-0.062l0.097-0.075 c0.309-0.246,0.651-0.371,0.832-0.402c0.313,0.138,0.662,0.212,1.016,0.212c1.199,0,2.412-0.82,3.166-2.139l0.59-1.032 C27.387,20.48,27.575,19.342,27.315,18.389z M25.274,20.635l-0.59,1.032c-0.438,0.765-1.104,1.251-1.639,1.251 c-0.133,0-0.258-0.029-0.369-0.094c-0.15-0.086-0.346-0.127-0.566-0.127c-0.596,0-1.383,0.295-2.01,0.796l-1.96,1.157 c-1.016,0.425-1.846,1.291-1.846,1.929s-0.898,1.159-1.998,1.159H13.14c-1.1,0-1.998-0.514-1.998-1.141s-0.834-1.477-1.854-1.888 l-2.046-1.157c-0.636-0.511-1.425-0.814-2.006-0.814c-0.202,0-0.379,0.037-0.516,0.115c-0.101,0.057-0.214,0.084-0.333,0.084 c-0.518,0-1.179-0.498-1.62-1.271l-0.591-1.032c-0.545-0.954-0.556-1.983-0.024-2.286c0.532-0.305,0.78-1.432,0.551-2.506 c0,0,0-0.003,0-1.042c0-1.088,0.021-1.18,0.021-1.18c0.238-1.072-0.01-2.203-0.552-2.513C1.631,10.8,1.634,9.765,2.18,8.812 L2.769,7.78c0.438-0.766,1.103-1.251,1.636-1.251c0.131,0,0.255,0.029,0.365,0.092C4.92,6.707,5.114,6.747,5.334,6.747 c0.596,0,1.38-0.296,2.007-0.795l1.944-1.065c1.021-0.407,1.856-1.277,1.856-1.933c0-0.656,0.898-1.192,1.998-1.192h1.156V1.761 c1.1,0,1.998,0.545,1.998,1.211c0,0.667,0.832,1.554,1.849,1.973L20,6.013c0.618,0.489,1.401,0.775,2.012,0.775 c0.24,0,0.454-0.045,0.62-0.139c0.122-0.069,0.259-0.102,0.403-0.102c0.551,0,1.221,0.476,1.653,1.231l0.59,1.032 c0.544,0.953,0.518,2.004-0.062,2.334c-0.577,0.331-0.859,1.48-0.627,2.554c0,0,0.01,0.042,0.01,1.103c0,1.012,0,1.012,0,1.012 c-0.218,1.049,0.068,2.174,0.636,2.498C25.802,18.635,25.819,19.68,25.274,20.635z"/><path d="M13.61,7.611c-3.913,0-7.084,3.173-7.084,7.085c0,3.914,3.171,7.085,7.084,7.085s7.085-3.172,7.085-7.085 C20.695,10.784,17.523,7.611,13.61,7.611z M13.61,20.02c-2.936,0-5.323-2.388-5.323-5.323c0-2.935,2.388-5.323,5.323-5.323 s5.324,2.388,5.324,5.323C18.934,17.632,16.546,20.02,13.61,20.02z"/><path d="M13.682,9.908c-2.602,0-4.718,2.116-4.718,4.718c0,2.601,2.116,4.716,4.718,4.716c2.601,0,4.717-2.115,4.717-4.716 C18.399,12.024,16.283,9.908,13.682,9.908z M13.682,17.581c-1.633,0-2.956-1.323-2.956-2.955s1.323-2.956,2.956-2.956 c1.632,0,2.956,1.324,2.956,2.956S15.314,17.581,13.682,17.581z"/></g></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="Capa_1" width="27.434" height="29.5" enable-background="new 0 0 27.434 29.5" version="1.1" viewBox="0 0 27.434 29.5" xml:space="preserve"><g><path d="M27.315,18.389c-0.165-0.604-0.509-1.113-0.981-1.459c-0.042-0.144-0.083-0.429-0.015-0.761l0.037-0.177v-0.182V14.8 c0-1.247-0.006-1.277-0.048-1.472c-0.076-0.354-0.035-0.653,0.007-0.803c0.477-0.346,0.828-0.861,0.996-1.476 c0.261-0.956,0.076-2.091-0.508-3.114l-0.591-1.032c-0.746-1.307-1.965-2.119-3.182-2.119c-0.378,0-0.75,0.081-1.085,0.235 c-0.198-0.025-0.554-0.15-0.855-0.389l-0.103-0.082l-0.114-0.065l-1.857-1.067L18.92,3.36l-0.105-0.044 c-0.376-0.154-0.658-0.41-0.768-0.556C17.918,1.172,16.349,0,14.296,0H13.14c-2.043,0-3.608,1.154-3.749,2.721 C9.277,2.862,8.999,3.104,8.633,3.25l-0.1,0.039L8.439,3.341L6.495,4.406L6.363,4.479L6.245,4.573 C5.936,4.82,5.596,4.944,5.416,4.977c-0.314-0.139-0.66-0.21-1.011-0.21c-1.198,0-2.411,0.819-3.165,2.139L0.65,7.938 c-0.412,0.72-0.642,1.521-0.644,2.258c-0.003,0.952,0.362,1.756,1.013,2.256c0.034,0.155,0.061,0.448-0.016,0.786 c-0.038,0.168-0.062,0.28-0.062,1.563c0,1.148,0,1.148,0.015,1.262l0.009,0.073l0.017,0.073c0.073,0.346,0.045,0.643,0.011,0.802 C0.348,17.512-0.01,18.314,0,19.268c0.008,0.729,0.238,1.523,0.648,2.242l0.589,1.031c0.761,1.331,1.967,2.159,3.15,2.159 c0.324,0,0.645-0.064,0.938-0.187c0.167,0.038,0.492,0.156,0.813,0.416l0.11,0.088l0.124,0.07l2.045,1.156l0.102,0.057l0.107,0.043 c0.364,0.147,0.646,0.381,0.766,0.521c0.164,1.52,1.719,2.634,3.745,2.634h1.155c2.037,0,3.598-1.134,3.747-2.675 c0.117-0.145,0.401-0.393,0.774-0.549l0.111-0.047l0.105-0.062l1.96-1.159l0.105-0.062l0.097-0.075 c0.309-0.246,0.651-0.371,0.832-0.402c0.313,0.138,0.662,0.212,1.016,0.212c1.199,0,2.412-0.82,3.166-2.139l0.59-1.032 C27.387,20.48,27.575,19.342,27.315,18.389z M25.274,20.635l-0.59,1.032c-0.438,0.765-1.104,1.251-1.639,1.251 c-0.133,0-0.258-0.029-0.369-0.094c-0.15-0.086-0.346-0.127-0.566-0.127c-0.596,0-1.383,0.295-2.01,0.796l-1.96,1.157 c-1.016,0.425-1.846,1.291-1.846,1.929s-0.898,1.159-1.998,1.159H13.14c-1.1,0-1.998-0.514-1.998-1.141s-0.834-1.477-1.854-1.888 l-2.046-1.157c-0.636-0.511-1.425-0.814-2.006-0.814c-0.202,0-0.379,0.037-0.516,0.115c-0.101,0.057-0.214,0.084-0.333,0.084 c-0.518,0-1.179-0.498-1.62-1.271l-0.591-1.032c-0.545-0.954-0.556-1.983-0.024-2.286c0.532-0.305,0.78-1.432,0.551-2.506 c0,0,0-0.003,0-1.042c0-1.088,0.021-1.18,0.021-1.18c0.238-1.072-0.01-2.203-0.552-2.513C1.631,10.8,1.634,9.765,2.18,8.812 L2.769,7.78c0.438-0.766,1.103-1.251,1.636-1.251c0.131,0,0.255,0.029,0.365,0.092C4.92,6.707,5.114,6.747,5.334,6.747 c0.596,0,1.38-0.296,2.007-0.795l1.944-1.065c1.021-0.407,1.856-1.277,1.856-1.933c0-0.656,0.898-1.192,1.998-1.192h1.156V1.761 c1.1,0,1.998,0.545,1.998,1.211c0,0.667,0.832,1.554,1.849,1.973L20,6.013c0.618,0.489,1.401,0.775,2.012,0.775 c0.24,0,0.454-0.045,0.62-0.139c0.122-0.069,0.259-0.102,0.403-0.102c0.551,0,1.221,0.476,1.653,1.231l0.59,1.032 c0.544,0.953,0.518,2.004-0.062,2.334c-0.577,0.331-0.859,1.48-0.627,2.554c0,0,0.01,0.042,0.01,1.103c0,1.012,0,1.012,0,1.012 c-0.218,1.049,0.068,2.174,0.636,2.498C25.802,18.635,25.819,19.68,25.274,20.635z"/><path d="M13.61,7.611c-3.913,0-7.084,3.173-7.084,7.085c0,3.914,3.171,7.085,7.084,7.085s7.085-3.172,7.085-7.085 C20.695,10.784,17.523,7.611,13.61,7.611z M13.61,20.02c-2.936,0-5.323-2.388-5.323-5.323c0-2.935,2.388-5.323,5.323-5.323 s5.324,2.388,5.324,5.323C18.934,17.632,16.546,20.02,13.61,20.02z"/><path d="M13.682,9.908c-2.602,0-4.718,2.116-4.718,4.718c0,2.601,2.116,4.716,4.718,4.716c2.601,0,4.717-2.115,4.717-4.716 C18.399,12.024,16.283,9.908,13.682,9.908z M13.682,17.581c-1.633,0-2.956-1.323-2.956-2.955s1.323-2.956,2.956-2.956 c1.632,0,2.956,1.324,2.956,2.956S15.314,17.581,13.682,17.581z"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.7 KiB |
|
|
@ -1,46 +1,14 @@
|
|||
#[inline]
|
||||
pub fn write_to_vec(vec: &mut Vec<u8>, byte: u8) {
|
||||
vec.push(byte);
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
const USIZE_LEB128_SIZE: usize = 5;
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
const USIZE_LEB128_SIZE: usize = 10;
|
||||
|
||||
macro_rules! leb128_size {
|
||||
(u16) => {
|
||||
3
|
||||
};
|
||||
(u32) => {
|
||||
5
|
||||
};
|
||||
(u64) => {
|
||||
10
|
||||
};
|
||||
(u128) => {
|
||||
19
|
||||
};
|
||||
(usize) => {
|
||||
USIZE_LEB128_SIZE
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! impl_write_unsigned_leb128 {
|
||||
($fn_name:ident, $int_ty:ident) => {
|
||||
#[inline]
|
||||
pub fn $fn_name(out: &mut Vec<u8>, mut value: $int_ty) {
|
||||
for _ in 0..leb128_size!($int_ty) {
|
||||
let mut byte = (value & 0x7F) as u8;
|
||||
value >>= 7;
|
||||
if value != 0 {
|
||||
byte |= 0x80;
|
||||
}
|
||||
|
||||
write_to_vec(out, byte);
|
||||
|
||||
if value == 0 {
|
||||
loop {
|
||||
if value < 0x80 {
|
||||
out.push(value as u8);
|
||||
break;
|
||||
} else {
|
||||
out.push(((value & 0x7f) | 0x80) as u8);
|
||||
value >>= 7;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -57,24 +25,20 @@ macro_rules! impl_read_unsigned_leb128 {
|
|||
($fn_name:ident, $int_ty:ident) => {
|
||||
#[inline]
|
||||
pub fn $fn_name(slice: &[u8]) -> ($int_ty, usize) {
|
||||
let mut result: $int_ty = 0;
|
||||
let mut result = 0;
|
||||
let mut shift = 0;
|
||||
let mut position = 0;
|
||||
|
||||
for _ in 0..leb128_size!($int_ty) {
|
||||
let byte = unsafe { *slice.get_unchecked(position) };
|
||||
loop {
|
||||
let byte = slice[position];
|
||||
position += 1;
|
||||
result |= ((byte & 0x7F) as $int_ty) << shift;
|
||||
if (byte & 0x80) == 0 {
|
||||
break;
|
||||
result |= (byte as $int_ty) << shift;
|
||||
return (result, position);
|
||||
} else {
|
||||
result |= ((byte & 0x7F) as $int_ty) << shift;
|
||||
}
|
||||
shift += 7;
|
||||
}
|
||||
|
||||
// Do a single bounds check at the end instead of for every byte.
|
||||
assert!(position <= slice.len());
|
||||
|
||||
(result, position)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -116,7 +80,7 @@ where
|
|||
|
||||
#[inline]
|
||||
pub fn write_signed_leb128(out: &mut Vec<u8>, value: i128) {
|
||||
write_signed_leb128_to(value, |v| write_to_vec(out, v))
|
||||
write_signed_leb128_to(value, |v| out.push(v))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
|||
|
|
@ -203,7 +203,7 @@ pub struct HashMap<K, V, S = RandomState> {
|
|||
base: base::HashMap<K, V, S>,
|
||||
}
|
||||
|
||||
impl<K: Hash + Eq, V> HashMap<K, V, RandomState> {
|
||||
impl<K, V> HashMap<K, V, RandomState> {
|
||||
/// Creates an empty `HashMap`.
|
||||
///
|
||||
/// The hash map is initially created with a capacity of 0, so it will not allocate until it
|
||||
|
|
@ -240,6 +240,59 @@ impl<K: Hash + Eq, V> HashMap<K, V, RandomState> {
|
|||
}
|
||||
|
||||
impl<K, V, S> HashMap<K, V, S> {
|
||||
/// Creates an empty `HashMap` which will use the given hash builder to hash
|
||||
/// keys.
|
||||
///
|
||||
/// The created map has the default initial capacity.
|
||||
///
|
||||
/// Warning: `hash_builder` is normally randomly generated, and
|
||||
/// is designed to allow HashMaps to be resistant to attacks that
|
||||
/// cause many collisions and very poor performance. Setting it
|
||||
/// manually using this function can expose a DoS attack vector.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::collections::HashMap;
|
||||
/// use std::collections::hash_map::RandomState;
|
||||
///
|
||||
/// let s = RandomState::new();
|
||||
/// let mut map = HashMap::with_hasher(s);
|
||||
/// map.insert(1, 2);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
|
||||
pub fn with_hasher(hash_builder: S) -> HashMap<K, V, S> {
|
||||
HashMap { base: base::HashMap::with_hasher(hash_builder) }
|
||||
}
|
||||
|
||||
/// Creates an empty `HashMap` with the specified capacity, using `hash_builder`
|
||||
/// to hash the keys.
|
||||
///
|
||||
/// The hash map will be able to hold at least `capacity` elements without
|
||||
/// reallocating. If `capacity` is 0, the hash map will not allocate.
|
||||
///
|
||||
/// Warning: `hash_builder` is normally randomly generated, and
|
||||
/// is designed to allow HashMaps to be resistant to attacks that
|
||||
/// cause many collisions and very poor performance. Setting it
|
||||
/// manually using this function can expose a DoS attack vector.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::collections::HashMap;
|
||||
/// use std::collections::hash_map::RandomState;
|
||||
///
|
||||
/// let s = RandomState::new();
|
||||
/// let mut map = HashMap::with_capacity_and_hasher(10, s);
|
||||
/// map.insert(1, 2);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
|
||||
pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> HashMap<K, V, S> {
|
||||
HashMap { base: base::HashMap::with_capacity_and_hasher(capacity, hash_builder) }
|
||||
}
|
||||
|
||||
/// Returns the number of elements the map can hold without reallocating.
|
||||
///
|
||||
/// This number is a lower bound; the `HashMap<K, V>` might be able to hold
|
||||
|
|
@ -457,65 +510,6 @@ impl<K, V, S> HashMap<K, V, S> {
|
|||
pub fn clear(&mut self) {
|
||||
self.base.clear();
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, V, S> HashMap<K, V, S>
|
||||
where
|
||||
K: Eq + Hash,
|
||||
S: BuildHasher,
|
||||
{
|
||||
/// Creates an empty `HashMap` which will use the given hash builder to hash
|
||||
/// keys.
|
||||
///
|
||||
/// The created map has the default initial capacity.
|
||||
///
|
||||
/// Warning: `hash_builder` is normally randomly generated, and
|
||||
/// is designed to allow HashMaps to be resistant to attacks that
|
||||
/// cause many collisions and very poor performance. Setting it
|
||||
/// manually using this function can expose a DoS attack vector.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::collections::HashMap;
|
||||
/// use std::collections::hash_map::RandomState;
|
||||
///
|
||||
/// let s = RandomState::new();
|
||||
/// let mut map = HashMap::with_hasher(s);
|
||||
/// map.insert(1, 2);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
|
||||
pub fn with_hasher(hash_builder: S) -> HashMap<K, V, S> {
|
||||
HashMap { base: base::HashMap::with_hasher(hash_builder) }
|
||||
}
|
||||
|
||||
/// Creates an empty `HashMap` with the specified capacity, using `hash_builder`
|
||||
/// to hash the keys.
|
||||
///
|
||||
/// The hash map will be able to hold at least `capacity` elements without
|
||||
/// reallocating. If `capacity` is 0, the hash map will not allocate.
|
||||
///
|
||||
/// Warning: `hash_builder` is normally randomly generated, and
|
||||
/// is designed to allow HashMaps to be resistant to attacks that
|
||||
/// cause many collisions and very poor performance. Setting it
|
||||
/// manually using this function can expose a DoS attack vector.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::collections::HashMap;
|
||||
/// use std::collections::hash_map::RandomState;
|
||||
///
|
||||
/// let s = RandomState::new();
|
||||
/// let mut map = HashMap::with_capacity_and_hasher(10, s);
|
||||
/// map.insert(1, 2);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
|
||||
pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> HashMap<K, V, S> {
|
||||
HashMap { base: base::HashMap::with_capacity_and_hasher(capacity, hash_builder) }
|
||||
}
|
||||
|
||||
/// Returns a reference to the map's [`BuildHasher`].
|
||||
///
|
||||
|
|
@ -536,7 +530,13 @@ where
|
|||
pub fn hasher(&self) -> &S {
|
||||
self.base.hasher()
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, V, S> HashMap<K, V, S>
|
||||
where
|
||||
K: Eq + Hash,
|
||||
S: BuildHasher,
|
||||
{
|
||||
/// Reserves capacity for at least `additional` more elements to be inserted
|
||||
/// in the `HashMap`. The collection may reserve more space to avoid
|
||||
/// frequent reallocations.
|
||||
|
|
@ -984,9 +984,8 @@ where
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<K, V, S> Debug for HashMap<K, V, S>
|
||||
where
|
||||
K: Eq + Hash + Debug,
|
||||
K: Debug,
|
||||
V: Debug,
|
||||
S: BuildHasher,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_map().entries(self.iter()).finish()
|
||||
|
|
@ -996,8 +995,7 @@ where
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<K, V, S> Default for HashMap<K, V, S>
|
||||
where
|
||||
K: Eq + Hash,
|
||||
S: BuildHasher + Default,
|
||||
S: Default,
|
||||
{
|
||||
/// Creates an empty `HashMap<K, V, S>`, with the `Default` value for the hasher.
|
||||
#[inline]
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ pub struct HashSet<T, S = RandomState> {
|
|||
map: HashMap<T, (), S>,
|
||||
}
|
||||
|
||||
impl<T: Hash + Eq> HashSet<T, RandomState> {
|
||||
impl<T> HashSet<T, RandomState> {
|
||||
/// Creates an empty `HashSet`.
|
||||
///
|
||||
/// The hash set is initially created with a capacity of 0, so it will not allocate until it
|
||||
|
|
@ -261,13 +261,7 @@ impl<T, S> HashSet<T, S> {
|
|||
pub fn clear(&mut self) {
|
||||
self.map.clear()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, S> HashSet<T, S>
|
||||
where
|
||||
T: Eq + Hash,
|
||||
S: BuildHasher,
|
||||
{
|
||||
/// Creates a new empty hash set which will use the given hasher to hash
|
||||
/// keys.
|
||||
///
|
||||
|
|
@ -340,7 +334,13 @@ where
|
|||
pub fn hasher(&self) -> &S {
|
||||
self.map.hasher()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, S> HashSet<T, S>
|
||||
where
|
||||
T: Eq + Hash,
|
||||
S: BuildHasher,
|
||||
{
|
||||
/// Reserves capacity for at least `additional` more elements to be inserted
|
||||
/// in the `HashSet`. The collection may reserve more space to avoid
|
||||
/// frequent reallocations.
|
||||
|
|
@ -928,8 +928,7 @@ where
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T, S> fmt::Debug for HashSet<T, S>
|
||||
where
|
||||
T: Eq + Hash + fmt::Debug,
|
||||
S: BuildHasher,
|
||||
T: fmt::Debug,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_set().entries(self.iter()).finish()
|
||||
|
|
@ -977,8 +976,7 @@ where
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T, S> Default for HashSet<T, S>
|
||||
where
|
||||
T: Eq + Hash,
|
||||
S: BuildHasher + Default,
|
||||
S: Default,
|
||||
{
|
||||
/// Creates an empty `HashSet<T, S>` with the `Default` value for the hasher.
|
||||
#[inline]
|
||||
|
|
|
|||
|
|
@ -22,12 +22,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8) {
|
|||
}
|
||||
}
|
||||
|
||||
pub unsafe fn cleanup() {
|
||||
let args = ARGS.swap(0, Ordering::Relaxed);
|
||||
if args != 0 {
|
||||
drop(Box::<ArgsStore>::from_raw(args as _))
|
||||
}
|
||||
}
|
||||
pub unsafe fn cleanup() {}
|
||||
|
||||
pub fn args() -> Args {
|
||||
let args = unsafe { (ARGS.load(Ordering::Relaxed) as *const ArgsStore).as_ref() };
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
#![allow(dead_code, unused_variables)]
|
||||
// run-rustfix
|
||||
// Check projection of an associated type out of a higher-ranked trait-bound
|
||||
// in the context of a function signature.
|
||||
|
||||
pub trait Foo<T> {
|
||||
type A;
|
||||
|
||||
fn get(&self, t: T) -> Self::A;
|
||||
}
|
||||
|
||||
fn foo2<I : for<'x> Foo<&'x isize>>(
|
||||
x: <I as Foo<&isize>>::A)
|
||||
//~^ ERROR cannot extract an associated type from a higher-ranked trait bound in this context
|
||||
{
|
||||
// This case is illegal because we have to instantiate `'x`, and
|
||||
// we don't know what region to instantiate it with.
|
||||
//
|
||||
// This could perhaps be made equivalent to the examples below,
|
||||
// specifically for fn signatures.
|
||||
}
|
||||
|
||||
fn foo3<I : for<'x> Foo<&'x isize>>(
|
||||
x: <I as Foo<&isize>>::A)
|
||||
{
|
||||
// OK, in this case we spelled out the precise regions involved, though we left one of
|
||||
// them anonymous.
|
||||
}
|
||||
|
||||
fn foo4<'a, I : for<'x> Foo<&'x isize>>(
|
||||
x: <I as Foo<&'a isize>>::A)
|
||||
{
|
||||
// OK, in this case we spelled out the precise regions involved.
|
||||
}
|
||||
|
||||
|
||||
pub fn main() {}
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
#![allow(dead_code, unused_variables)]
|
||||
// run-rustfix
|
||||
// Check projection of an associated type out of a higher-ranked trait-bound
|
||||
// in the context of a function signature.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
error[E0212]: cannot extract an associated type from a higher-ranked trait bound in this context
|
||||
--> $DIR/associated-types-project-from-hrtb-in-fn.rs:11:8
|
||||
--> $DIR/associated-types-project-from-hrtb-in-fn.rs:13:8
|
||||
|
|
||||
LL | x: I::A)
|
||||
| ^^^^
|
||||
| ^^^^ help: use a fully qualified path with inferred lifetimes: `<I as Foo<&isize>>::A`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -7,18 +7,25 @@ pub trait Foo<T> {
|
|||
fn get(&self, t: T) -> Self::A;
|
||||
}
|
||||
|
||||
struct SomeStruct<I : for<'x> Foo<&'x isize>> {
|
||||
struct SomeStruct<I: for<'x> Foo<&'x isize>> {
|
||||
field: I::A
|
||||
//~^ ERROR cannot extract an associated type from a higher-ranked trait bound in this context
|
||||
}
|
||||
|
||||
enum SomeEnum<I: for<'x> Foo<&'x isize>> {
|
||||
TupleVariant(I::A),
|
||||
//~^ ERROR cannot extract an associated type from a higher-ranked trait bound in this context
|
||||
StructVariant { field: I::A },
|
||||
//~^ ERROR cannot extract an associated type from a higher-ranked trait bound in this context
|
||||
}
|
||||
|
||||
// FIXME(eddyb) This one doesn't even compile because of the unsupported syntax.
|
||||
|
||||
// struct AnotherStruct<I : for<'x> Foo<&'x isize>> {
|
||||
// field: <I as for<'y> Foo<&'y isize>>::A
|
||||
// }
|
||||
|
||||
struct YetAnotherStruct<'a, I : for<'x> Foo<&'x isize>> {
|
||||
struct YetAnotherStruct<'a, I: for<'x> Foo<&'x isize>> {
|
||||
field: <I as Foo<&'a isize>>::A
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,38 @@ error[E0212]: cannot extract an associated type from a higher-ranked trait bound
|
|||
|
|
||||
LL | field: I::A
|
||||
| ^^^^
|
||||
|
|
||||
help: use a fully qualified path with explicit lifetimes
|
||||
|
|
||||
LL | struct SomeStruct<'a, I: for<'x> Foo<&'x isize>> {
|
||||
LL | field: <I as Foo<&'a isize>>::A
|
||||
|
|
||||
|
||||
error: aborting due to previous error
|
||||
error[E0212]: cannot extract an associated type from a higher-ranked trait bound in this context
|
||||
--> $DIR/associated-types-project-from-hrtb-in-struct.rs:16:18
|
||||
|
|
||||
LL | TupleVariant(I::A),
|
||||
| ^^^^
|
||||
|
|
||||
help: use a fully qualified path with explicit lifetimes
|
||||
|
|
||||
LL | enum SomeEnum<'a, I: for<'x> Foo<&'x isize>> {
|
||||
LL | TupleVariant(<I as Foo<&'a isize>>::A),
|
||||
|
|
||||
|
||||
error[E0212]: cannot extract an associated type from a higher-ranked trait bound in this context
|
||||
--> $DIR/associated-types-project-from-hrtb-in-struct.rs:18:28
|
||||
|
|
||||
LL | StructVariant { field: I::A },
|
||||
| ^^^^
|
||||
|
|
||||
help: use a fully qualified path with explicit lifetimes
|
||||
|
|
||||
LL | enum SomeEnum<'a, I: for<'x> Foo<&'x isize>> {
|
||||
LL | TupleVariant(I::A),
|
||||
LL |
|
||||
LL | StructVariant { field: <I as Foo<&'a isize>>::A },
|
||||
|
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
#![allow(dead_code)]
|
||||
// run-rustfix
|
||||
// Check projection of an associated type out of a higher-ranked trait-bound
|
||||
// in the context of a method definition in a trait.
|
||||
|
||||
pub trait Foo<T> {
|
||||
type A;
|
||||
|
||||
fn get(&self, t: T) -> Self::A;
|
||||
}
|
||||
|
||||
trait SomeTrait<I : for<'x> Foo<&'x isize>> {
|
||||
fn some_method(&self, arg: <I as Foo<&isize>>::A);
|
||||
//~^ ERROR cannot extract an associated type from a higher-ranked trait bound in this context
|
||||
}
|
||||
|
||||
trait AnotherTrait<I : for<'x> Foo<&'x isize>> {
|
||||
fn some_method(&self, arg: <I as Foo<&isize>>::A);
|
||||
}
|
||||
|
||||
trait YetAnotherTrait<I : for<'x> Foo<&'x isize>> {
|
||||
fn some_method<'a>(&self, arg: <I as Foo<&'a isize>>::A);
|
||||
}
|
||||
|
||||
trait Banana<'a> {
|
||||
type Assoc: Default;
|
||||
}
|
||||
|
||||
struct Peach<X>(std::marker::PhantomData<X>);
|
||||
|
||||
impl<X: for<'a> Banana<'a>> Peach<X> {
|
||||
fn mango(&self) -> <X as Banana<'_>>::Assoc {
|
||||
//~^ ERROR cannot extract an associated type from a higher-ranked trait bound in this context
|
||||
Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() {}
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
#![allow(dead_code)]
|
||||
// run-rustfix
|
||||
// Check projection of an associated type out of a higher-ranked trait-bound
|
||||
// in the context of a method definition in a trait.
|
||||
|
||||
|
|
@ -20,4 +22,17 @@ trait YetAnotherTrait<I : for<'x> Foo<&'x isize>> {
|
|||
fn some_method<'a>(&self, arg: <I as Foo<&'a isize>>::A);
|
||||
}
|
||||
|
||||
trait Banana<'a> {
|
||||
type Assoc: Default;
|
||||
}
|
||||
|
||||
struct Peach<X>(std::marker::PhantomData<X>);
|
||||
|
||||
impl<X: for<'a> Banana<'a>> Peach<X> {
|
||||
fn mango(&self) -> X::Assoc {
|
||||
//~^ ERROR cannot extract an associated type from a higher-ranked trait bound in this context
|
||||
Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() {}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,14 @@
|
|||
error[E0212]: cannot extract an associated type from a higher-ranked trait bound in this context
|
||||
--> $DIR/associated-types-project-from-hrtb-in-trait-method.rs:11:32
|
||||
--> $DIR/associated-types-project-from-hrtb-in-trait-method.rs:13:32
|
||||
|
|
||||
LL | fn some_method(&self, arg: I::A);
|
||||
| ^^^^
|
||||
| ^^^^ help: use a fully qualified path with inferred lifetimes: `<I as Foo<&isize>>::A`
|
||||
|
||||
error: aborting due to previous error
|
||||
error[E0212]: cannot extract an associated type from a higher-ranked trait bound in this context
|
||||
--> $DIR/associated-types-project-from-hrtb-in-trait-method.rs:32:24
|
||||
|
|
||||
LL | fn mango(&self) -> X::Assoc {
|
||||
| ^^^^^^^^ help: use a fully qualified path with inferred lifetimes: `<X as Banana<'_>>::Assoc`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ pub fn no_debug() {
|
|||
pub fn no_hash() {
|
||||
use std::collections::HashSet;
|
||||
let mut set = HashSet::new();
|
||||
//~^ ERROR arrays only have std trait implementations for lengths 0..=32
|
||||
set.insert([0_usize; 33]);
|
||||
//~^ ERROR arrays only have std trait implementations for lengths 0..=32
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,24 +9,15 @@ LL | println!("{:?}", [0_usize; 33]);
|
|||
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0277]: arrays only have std trait implementations for lengths 0..=32
|
||||
--> $DIR/core-traits-no-impls-length-33.rs:10:16
|
||||
--> $DIR/core-traits-no-impls-length-33.rs:9:16
|
||||
|
|
||||
LL | set.insert([0_usize; 33]);
|
||||
| ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[usize; 33]`
|
||||
|
|
||||
= note: required because of the requirements on the impl of `std::cmp::Eq` for `[usize; 33]`
|
||||
|
||||
error[E0277]: arrays only have std trait implementations for lengths 0..=32
|
||||
--> $DIR/core-traits-no-impls-length-33.rs:8:19
|
||||
|
|
||||
LL | let mut set = HashSet::new();
|
||||
| ^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[usize; 33]`
|
||||
|
|
||||
= note: required because of the requirements on the impl of `std::cmp::Eq` for `[usize; 33]`
|
||||
= note: required by `std::collections::HashSet::<T>::new`
|
||||
|
||||
error[E0369]: binary operation `==` cannot be applied to type `[usize; 33]`
|
||||
--> $DIR/core-traits-no-impls-length-33.rs:15:19
|
||||
--> $DIR/core-traits-no-impls-length-33.rs:14:19
|
||||
|
|
||||
LL | [0_usize; 33] == [1_usize; 33]
|
||||
| ------------- ^^ ------------- [usize; 33]
|
||||
|
|
@ -36,7 +27,7 @@ LL | [0_usize; 33] == [1_usize; 33]
|
|||
= note: an implementation of `std::cmp::PartialEq` might be missing for `[usize; 33]`
|
||||
|
||||
error[E0369]: binary operation `<` cannot be applied to type `[usize; 33]`
|
||||
--> $DIR/core-traits-no-impls-length-33.rs:20:19
|
||||
--> $DIR/core-traits-no-impls-length-33.rs:19:19
|
||||
|
|
||||
LL | [0_usize; 33] < [1_usize; 33]
|
||||
| ------------- ^ ------------- [usize; 33]
|
||||
|
|
@ -46,7 +37,7 @@ LL | [0_usize; 33] < [1_usize; 33]
|
|||
= note: an implementation of `std::cmp::PartialOrd` might be missing for `[usize; 33]`
|
||||
|
||||
error[E0277]: the trait bound `&[usize; 33]: std::iter::IntoIterator` is not satisfied
|
||||
--> $DIR/core-traits-no-impls-length-33.rs:25:14
|
||||
--> $DIR/core-traits-no-impls-length-33.rs:24:14
|
||||
|
|
||||
LL | for _ in &[0_usize; 33] {
|
||||
| ^^^^^^^^^^^^^^ the trait `std::iter::IntoIterator` is not implemented for `&[usize; 33]`
|
||||
|
|
@ -58,7 +49,7 @@ LL | for _ in &[0_usize; 33] {
|
|||
<&'a mut [T] as std::iter::IntoIterator>
|
||||
= note: required by `std::iter::IntoIterator::into_iter`
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0369.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
||||
|
|
|
|||
|
|
@ -11,5 +11,5 @@ fn main() {
|
|||
let mut generator = static || {
|
||||
yield;
|
||||
};
|
||||
assert_unpin(generator); //~ ERROR std::marker::Unpin` is not satisfied
|
||||
assert_unpin(generator); //~ ERROR E0277
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
error[E0277]: the trait bound `[static generator@$DIR/static-not-unpin.rs:11:25: 13:6 _]: std::marker::Unpin` is not satisfied
|
||||
error[E0277]: `[static generator@$DIR/static-not-unpin.rs:11:25: 13:6 _]` cannot be unpinned
|
||||
--> $DIR/static-not-unpin.rs:14:18
|
||||
|
|
||||
LL | fn assert_unpin<T: Unpin>(_: T) {
|
||||
|
|
|
|||
29
src/test/ui/suggestions/expected-boxed-future-isnt-pinned.rs
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
// edition:2018
|
||||
#![allow(dead_code)]
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
|
||||
type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
|
||||
// ^^^^^^^^^ This would come from the `futures` crate in real code.
|
||||
|
||||
fn foo<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
|
||||
// We could instead use an `async` block, but this way we have no std spans.
|
||||
x //~ ERROR mismatched types
|
||||
}
|
||||
|
||||
// FIXME: uncomment these once this commit is in Beta and we can rely on `rustc_on_unimplemented`
|
||||
// having filtering for `Self` being a trait.
|
||||
//
|
||||
// fn bar<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
|
||||
// Box::new(x)
|
||||
// }
|
||||
//
|
||||
// fn baz<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
|
||||
// Pin::new(x)
|
||||
// }
|
||||
//
|
||||
// fn qux<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
|
||||
// Pin::new(Box::new(x))
|
||||
// }
|
||||
|
||||
fn main() {}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/expected-boxed-future-isnt-pinned.rs:11:5
|
||||
|
|
||||
LL | fn foo<F: Future<Output=i32> + Send + 'static>(x: F) -> BoxFuture<'static, i32> {
|
||||
| - this type parameter ----------------------- expected `std::pin::Pin<std::boxed::Box<(dyn std::future::Future<Output = i32> + std::marker::Send + 'static)>>` because of return type
|
||||
LL | // We could instead use an `async` block, but this way we have no std spans.
|
||||
LL | x
|
||||
| ^
|
||||
| |
|
||||
| expected struct `std::pin::Pin`, found type parameter `F`
|
||||
| help: you need to pin and box this expression: `Box::pin(x)`
|
||||
|
|
||||
= note: expected struct `std::pin::Pin<std::boxed::Box<(dyn std::future::Future<Output = i32> + std::marker::Send + 'static)>>`
|
||||
found type parameter `F`
|
||||
= help: type parameters must be constrained to match other types
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
// check-pass
|
||||
// Regression test for issue #67844
|
||||
// Ensures that we properly handle nested TAIT occurences
|
||||
// with generic parameters
|
||||
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
trait WithAssoc { type AssocType; }
|
||||
|
||||
trait WithParam<A> {}
|
||||
|
||||
type Return<A> = impl WithAssoc<AssocType = impl WithParam<A>>;
|
||||
|
||||
struct MyParam;
|
||||
impl<A> WithParam<A> for MyParam {}
|
||||
|
||||
struct MyStruct;
|
||||
|
||||
impl WithAssoc for MyStruct {
|
||||
type AssocType = MyParam;
|
||||
}
|
||||
|
||||
|
||||
fn my_fun<A>() -> Return<A> {
|
||||
MyStruct
|
||||
}
|
||||
|
||||
fn my_other_fn<A>() -> impl WithAssoc<AssocType = impl WithParam<A>> {
|
||||
MyStruct
|
||||
}
|
||||
|
||||
fn main() {}
|
||||