diff --git a/src/libextra/fileinput.rs b/src/libextra/fileinput.rs index 3b4fad3eaa7..009198b9b6e 100644 --- a/src/libextra/fileinput.rs +++ b/src/libextra/fileinput.rs @@ -27,7 +27,7 @@ reset once it has been finished, so attempting to iterate on `[None, None]` will only take input once unless `io::stdin().seek(0, SeekSet)` is called between. -The `pathify` function handles converting a list of file paths as +The `make_path_option_vec` function handles converting a list of file paths as strings to the appropriate format, including the (optional) conversion of `"-"` to `stdin`. @@ -42,7 +42,7 @@ to handle any `FileInput` structs. E.g. a simple `cat` program or a program that numbers lines after concatenating two files - for input_vec_state(pathify([~"a.txt", ~"b.txt"])) |line, state| { + for input_vec_state(make_path_option_vec([~"a.txt", ~"b.txt"])) |line, state| { io::println(fmt!("%u: %s", state.line_num, line)); } @@ -145,8 +145,14 @@ struct FileInput_ { previous_was_newline: bool } -// XXX: remove this when Reader has &mut self. Should be removable via -// "self.fi." -> "self." and renaming FileInput_. Documentation above + +// FIXME #5723: remove this when Reader has &mut self. +// Removing it would mean giving read_byte in the Reader impl for +// FileInput &mut self, which in turn means giving most of the +// io::Reader trait methods &mut self. That can't be done right now +// because of io::with_bytes_reader and #5723. +// Should be removable via +// "self.fi" -> "self." and renaming FileInput_. Documentation above // will likely have to be updated to use `let mut in = ...`. pub struct FileInput { fi: @mut FileInput_ @@ -194,7 +200,7 @@ impl FileInput { */ pub fn from_args() -> FileInput { let args = os::args(); - let pathed = pathify(args.tail(), true); + let pathed = make_path_option_vec(args.tail(), true); FileInput::from_vec(pathed) } @@ -351,8 +357,7 @@ Convert a list of strings to an appropriate form for a `FileInput` instance. `stdin_hyphen` controls whether `-` represents `stdin` or a literal `-`. */ -// XXX: stupid, unclear name -pub fn pathify(vec: &[~str], stdin_hyphen : bool) -> ~[Option] { +pub fn make_path_option_vec(vec: &[~str], stdin_hyphen : bool) -> ~[Option] { vec.iter().map(|str| { if stdin_hyphen && "-" == *str { None @@ -410,7 +415,7 @@ pub fn input_vec_state(files: ~[Option], #[cfg(test)] mod test { - use super::{FileInput, pathify, input_vec, input_vec_state}; + use super::{FileInput, make_path_option_vec, input_vec, input_vec_state}; use std::io; use std::uint; @@ -426,22 +431,22 @@ mod test { } #[test] - fn test_pathify() { + fn test_make_path_option_vec() { let strs = [~"some/path", ~"some/other/path"]; let paths = ~[Some(Path("some/path")), Some(Path("some/other/path"))]; - assert_eq!(pathify(strs, true), paths.clone()); - assert_eq!(pathify(strs, false), paths); + assert_eq!(make_path_option_vec(strs, true), paths.clone()); + assert_eq!(make_path_option_vec(strs, false), paths); - assert_eq!(pathify([~"-"], true), ~[None]); - assert_eq!(pathify([~"-"], false), ~[Some(Path("-"))]); + assert_eq!(make_path_option_vec([~"-"], true), ~[None]); + assert_eq!(make_path_option_vec([~"-"], false), ~[Some(Path("-"))]); } #[test] fn test_fileinput_read_byte() { - let filenames = pathify(vec::from_fn( + let filenames = make_path_option_vec(vec::from_fn( 3, |i| fmt!("tmp/lib-fileinput-test-fileinput-read-byte-%u.tmp", i)), true); @@ -471,7 +476,7 @@ mod test { #[test] fn test_fileinput_read() { - let filenames = pathify(vec::from_fn( + let filenames = make_path_option_vec(vec::from_fn( 3, |i| fmt!("tmp/lib-fileinput-test-fileinput-read-%u.tmp", i)), true); @@ -492,7 +497,7 @@ mod test { #[test] fn test_input_vec() { let mut all_lines = ~[]; - let filenames = pathify(vec::from_fn( + let filenames = make_path_option_vec(vec::from_fn( 3, |i| fmt!("tmp/lib-fileinput-test-input-vec-%u.tmp", i)), true); @@ -514,7 +519,7 @@ mod test { #[test] fn test_input_vec_state() { - let filenames = pathify(vec::from_fn( + let filenames = make_path_option_vec(vec::from_fn( 3, |i| fmt!("tmp/lib-fileinput-test-input-vec-state-%u.tmp", i)),true); @@ -536,7 +541,7 @@ mod test { #[test] fn test_empty_files() { - let filenames = pathify(vec::from_fn( + let filenames = make_path_option_vec(vec::from_fn( 3, |i| fmt!("tmp/lib-fileinput-test-empty-files-%u.tmp", i)),true); @@ -583,7 +588,7 @@ mod test { #[test] fn test_next_file() { - let filenames = pathify(vec::from_fn( + let filenames = make_path_option_vec(vec::from_fn( 3, |i| fmt!("tmp/lib-fileinput-test-next-file-%u.tmp", i)),true); @@ -614,7 +619,7 @@ mod test { #[test] #[should_fail] fn test_input_vec_missing_file() { - do input_vec(pathify([~"this/file/doesnt/exist"], true)) |line| { + do input_vec(make_path_option_vec([~"this/file/doesnt/exist"], true)) |line| { println(line); true }; diff --git a/src/libextra/flatpipes.rs b/src/libextra/flatpipes.rs index aa7c6433f1f..daad3970445 100644 --- a/src/libextra/flatpipes.rs +++ b/src/libextra/flatpipes.rs @@ -564,8 +564,10 @@ pub mod bytepipes { } } - // XXX: Remove `@mut` when this module is ported to the new I/O traits, - // which use `&mut self` properly. + // FIXME #6850: Remove `@mut` when this module is ported to the new I/O traits, + // which use `&mut self` properly. (For example, util::comm::GenericPort's try_recv + // method doesn't use `&mut self`, so the `try_recv` method in the impl of `BytePort` + // for `PipeBytePort` can't have `&mut self` either.) pub struct PipeBytePort { port: comm::Port<~[u8]>, buf: @mut ~[u8] diff --git a/src/libextra/io_util.rs b/src/libextra/io_util.rs index afefca8ae65..b75295ffd22 100644 --- a/src/libextra/io_util.rs +++ b/src/libextra/io_util.rs @@ -30,7 +30,7 @@ impl BufReader { } fn as_bytes_reader(&self, f: &fn(&BytesReader) -> A) -> A { - // XXX FIXME(#5723) + // FIXME(#5723) let bytes = ::std::util::id::<&[u8]>(self.buf); let bytes: &'static [u8] = unsafe { cast::transmute(bytes) }; // Recreating the BytesReader state every call since diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index 9654bf3fc01..2e8748e4ff8 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -831,6 +831,7 @@ pub fn Resolver(session: Session, trait_map: HashMap::new(), used_imports: HashSet::new(), + emit_errors: true, intr: session.intr() }; @@ -888,6 +889,11 @@ pub struct Resolver { export_map2: ExportMap2, trait_map: TraitMap, + // Whether or not to print error messages. Can be set to true + // when getting additional info for error message suggestions, + // so as to avoid printing duplicate errors + emit_errors: bool, + used_imports: HashSet, } @@ -1072,7 +1078,7 @@ impl Resolver { // Return an error here by looking up the namespace that // had the duplicate. let ns = ns.unwrap(); - self.session.span_err(sp, + self.resolve_error(sp, fmt!("duplicate definition of %s `%s`", namespace_error_to_str(duplicate_type), self.session.str_of(name))); @@ -2074,7 +2080,7 @@ impl Resolver { self.import_path_to_str( import_directive.module_path, *import_directive.subclass)); - self.session.span_err(import_directive.span, msg); + self.resolve_error(import_directive.span, msg); } Indeterminate => { // Bail out. We'll come around next time. @@ -2249,9 +2255,6 @@ impl Resolver { // We need to resolve both namespaces for this to succeed. // - // FIXME #4949: See if there's some way of handling namespaces in - // a more generic way. We have two of them; it seems worth - // doing... let mut value_result = UnknownResult; let mut type_result = UnknownResult; @@ -2448,12 +2451,12 @@ impl Resolver { let span = directive.span; if resolve_fail { - self.session.span_err(span, fmt!("unresolved import: there is no `%s` in `%s`", + self.resolve_error(span, fmt!("unresolved import: there is no `%s` in `%s`", self.session.str_of(source), self.module_to_str(containing_module))); return Failed; } else if priv_fail { - self.session.span_err(span, fmt!("unresolved import: found `%s` in `%s` but it is \ + self.resolve_error(span, fmt!("unresolved import: found `%s` in `%s` but it is \ private", self.session.str_of(source), self.module_to_str(containing_module))); return Failed; @@ -2620,14 +2623,14 @@ impl Resolver { hi: span.lo + BytePos(segment_name.len()), expn_info: span.expn_info, }; - self.session.span_err(span, + self.resolve_error(span, fmt!("unresolved import. maybe \ a missing `extern mod \ %s`?", segment_name)); return Failed; } - self.session.span_err(span, fmt!("unresolved import: could not find `%s` in \ + self.resolve_error(span, fmt!("unresolved import: could not find `%s` in \ `%s`.", segment_name, module_name)); return Failed; } @@ -2645,7 +2648,7 @@ impl Resolver { match type_def.module_def { None => { // Not a module. - self.session.span_err(span, + self.resolve_error(span, fmt!("not a \ module `%s`", self.session. @@ -2661,7 +2664,7 @@ impl Resolver { module_def.kind) { (ImportSearch, TraitModuleKind) | (ImportSearch, ImplModuleKind) => { - self.session.span_err( + self.resolve_error( span, "cannot import from a trait \ or type implementation"); @@ -2674,7 +2677,7 @@ impl Resolver { } None => { // There are no type bindings at all. - self.session.span_err(span, + self.resolve_error(span, fmt!("not a module `%s`", self.session.str_of( name))); @@ -2726,7 +2729,7 @@ impl Resolver { let mpath = self.idents_to_str(module_path); match mpath.rfind(':') { Some(idx) => { - self.session.span_err(span, fmt!("unresolved import: could not find `%s` \ + self.resolve_error(span, fmt!("unresolved import: could not find `%s` \ in `%s`", // idx +- 1 to account for the colons // on either side @@ -2762,8 +2765,7 @@ impl Resolver { module_path[0]); match result { Failed => { - self.session.span_err(span, - "unresolved name"); + self.resolve_error(span, "unresolved name"); return Failed; } Indeterminate => { @@ -3143,11 +3145,11 @@ impl Resolver { if index != import_count { let sn = self.session.codemap.span_to_snippet(imports[index].span).unwrap(); if sn.contains("::") { - self.session.span_err(imports[index].span, "unresolved import"); + self.resolve_error(imports[index].span, "unresolved import"); } else { let err = fmt!("unresolved import (maybe you meant `%s::*`?)", sn.slice(0, sn.len())); - self.session.span_err(imports[index].span, err); + self.resolve_error(imports[index].span, err); } } @@ -3412,7 +3414,7 @@ impl Resolver { // named function item. This is not allowed, so we // report an error. - self.session.span_err( + self.resolve_error( span, "can't capture dynamic environment in a fn item; \ use the || { ... } closure form instead"); @@ -3420,7 +3422,7 @@ impl Resolver { // This was an attempt to use a type parameter outside // its scope. - self.session.span_err(span, + self.resolve_error(span, "attempt to use a type \ argument out of scope"); } @@ -3435,7 +3437,7 @@ impl Resolver { // named function item. This is not allowed, so we // report an error. - self.session.span_err( + self.resolve_error( span, "can't capture dynamic environment in a fn item; \ use the || { ... } closure form instead"); @@ -3443,7 +3445,7 @@ impl Resolver { // This was an attempt to use a type parameter outside // its scope. - self.session.span_err(span, + self.resolve_error(span, "attempt to use a type \ argument out of scope"); } @@ -3452,7 +3454,7 @@ impl Resolver { } ConstantItemRibKind => { // Still doesn't deal with upvars - self.session.span_err(span, + self.resolve_error(span, "attempt to use a non-constant \ value in a constant"); @@ -3849,7 +3851,7 @@ impl Resolver { }; let msg = fmt!("attempt to %s a nonexistent trait `%s`", usage_str, path_str); - self.session.span_err(trait_reference.path.span, msg); + self.resolve_error(trait_reference.path.span, msg); } Some(def) => { debug!("(resolving trait) found trait def: %?", def); @@ -3870,7 +3872,7 @@ impl Resolver { match ident_map.find(&ident) { Some(&prev_field) => { let ident_str = self.session.str_of(ident); - self.session.span_err(field.span, + self.resolve_error(field.span, fmt!("field `%s` is already declared", ident_str)); self.session.span_note(prev_field.span, "Previously declared here"); @@ -4055,7 +4057,7 @@ impl Resolver { for (&key, &binding_0) in map_0.iter() { match map_i.find(&key) { None => { - self.session.span_err( + self.resolve_error( p.span, fmt!("variable `%s` from pattern #1 is \ not bound in pattern #%u", @@ -4063,7 +4065,7 @@ impl Resolver { } Some(binding_i) => { if binding_0.binding_mode != binding_i.binding_mode { - self.session.span_err( + self.resolve_error( binding_i.span, fmt!("variable `%s` is bound with different \ mode in pattern #%u than in pattern #1", @@ -4075,7 +4077,7 @@ impl Resolver { for (&key, &binding) in map_i.iter() { if !map_0.contains_key(&key) { - self.session.span_err( + self.resolve_error( binding.span, fmt!("variable `%s` from pattern #%u is \ not bound in pattern #1", @@ -4188,7 +4190,7 @@ impl Resolver { self.record_def(path_id, def); } None => { - self.session.span_err + self.resolve_error (ty.span, fmt!("use of undeclared type name `%s`", self.idents_to_str(path.idents))); } @@ -4256,7 +4258,7 @@ impl Resolver { self.record_def(pattern.id, def); } FoundStructOrEnumVariant(_) => { - self.session.span_err(pattern.span, + self.resolve_error(pattern.span, fmt!("declaration of `%s` \ shadows an enum \ variant or unit-like \ @@ -4276,7 +4278,7 @@ impl Resolver { self.record_def(pattern.id, def); } FoundConst(_) => { - self.session.span_err(pattern.span, + self.resolve_error(pattern.span, "only refutable patterns \ allowed here"); } @@ -4330,7 +4332,7 @@ impl Resolver { // Then this is a duplicate variable // in the same disjunct, which is an // error - self.session.span_err(pattern.span, + self.resolve_error(pattern.span, fmt!("Identifier `%s` is bound more \ than once in the same pattern", path_to_str(path, self.session @@ -4370,14 +4372,14 @@ impl Resolver { self.record_def(pattern.id, def); } Some(_) => { - self.session.span_err( + self.resolve_error( path.span, fmt!("`%s` is not an enum variant or constant", self.session.str_of( *path.idents.last()))); } None => { - self.session.span_err(path.span, + self.resolve_error(path.span, "unresolved enum variant"); } } @@ -4398,14 +4400,14 @@ impl Resolver { self.record_def(pattern.id, def); } Some(_) => { - self.session.span_err( + self.resolve_error( path.span, fmt!("`%s` is not an enum variant, struct or const", self.session.str_of( *path.idents.last()))); } None => { - self.session.span_err(path.span, + self.resolve_error(path.span, "unresolved enum variant, \ struct or const"); } @@ -4444,7 +4446,7 @@ impl Resolver { result => { debug!("(resolving pattern) didn't find struct \ def: %?", result); - self.session.span_err( + self.resolve_error( path.span, fmt!("`%s` does not name a structure", self.idents_to_str(path.idents))); @@ -4664,7 +4666,7 @@ impl Resolver { path.span, PathPublicOnlySearch) { Failed => { - self.session.span_err(path.span, + self.resolve_error(path.span, fmt!("use of undeclared module `%s`", self.idents_to_str( module_path_idents))); @@ -4732,7 +4734,7 @@ impl Resolver { path.span, PathPublicOrPrivateSearch) { Failed => { - self.session.span_err(path.span, + self.resolve_error(path.span, fmt!("use of undeclared module `::%s`", self.idents_to_str( module_path_idents))); @@ -4858,6 +4860,19 @@ impl Resolver { } } + fn with_no_errors(@mut self, f: &fn() -> T) -> T { + self.emit_errors = false; + let rs = f(); + self.emit_errors = true; + rs + } + + fn resolve_error(@mut self, span: span, s: &str) { + if self.emit_errors { + self.session.span_err(span, s); + } + } + pub fn find_best_match_for_name(@mut self, name: &str, max_distance: uint) @@ -4957,7 +4972,7 @@ impl Resolver { // out here. match def { def_method(*) => { - self.session.span_err(expr.span, + self.resolve_error(expr.span, "first-class methods \ are not supported"); self.session.span_note(expr.span, @@ -4974,27 +4989,45 @@ impl Resolver { let wrong_name = self.idents_to_str( path.idents); if self.name_exists_in_scope_struct(wrong_name) { - self.session.span_err(expr.span, + self.resolve_error(expr.span, fmt!("unresolved name `%s`. \ Did you mean `self.%s`?", wrong_name, wrong_name)); } else { - // limit search to 5 to reduce the number - // of stupid suggestions - match self.find_best_match_for_name(wrong_name, 5) { - Some(m) => { - self.session.span_err(expr.span, - fmt!("unresolved name `%s`. \ - Did you mean `%s`?", - wrong_name, m)); - } - None => { - self.session.span_err(expr.span, - fmt!("unresolved name `%s`.", - wrong_name)); + // Be helpful if the name refers to a struct + // (The pattern matching def_tys where the id is in self.structs + // matches on regular structs while excluding tuple- and enum-like + // structs, which wouldn't result in this error.) + match self.with_no_errors(|| + self.resolve_path(expr.id, path, TypeNS, false, visitor)) { + Some(def_ty(struct_id)) + if self.structs.contains(&struct_id) => { + self.resolve_error(expr.span, + fmt!("`%s` is a structure name, but this expression \ + uses it like a function name", wrong_name)); + + self.session.span_note(expr.span, fmt!("Did you mean to write: \ + `%s { /* fields */ }`?", wrong_name)); + } + _ => + // limit search to 5 to reduce the number + // of stupid suggestions + match self.find_best_match_for_name(wrong_name, 5) { + Some(m) => { + self.resolve_error(expr.span, + fmt!("unresolved name `%s`. \ + Did you mean `%s`?", + wrong_name, m)); + } + None => { + self.resolve_error(expr.span, + fmt!("unresolved name `%s`.", + wrong_name)); + } + } } } } @@ -5027,7 +5060,7 @@ impl Resolver { result => { debug!("(resolving expression) didn't find struct \ def: %?", result); - self.session.span_err( + self.resolve_error( path.span, fmt!("`%s` does not name a structure", self.idents_to_str(path.idents))); @@ -5056,7 +5089,7 @@ impl Resolver { match self.search_ribs(self.label_ribs, label, expr.span, DontAllowCapturingSelf) { None => - self.session.span_err(expr.span, + self.resolve_error(expr.span, fmt!("use of undeclared label \ `%s`", self.session.str_of( @@ -5075,7 +5108,7 @@ impl Resolver { expr_self => { match self.resolve_self_value_in_local_ribs(expr.span) { None => { - self.session.span_err(expr.span, + self.resolve_error(expr.span, "`self` is not allowed in \ this context") } @@ -5306,7 +5339,7 @@ impl Resolver { match pat_binding_mode { bind_infer => {} bind_by_ref(*) => { - self.session.span_err( + self.resolve_error( pat.span, fmt!("cannot use `ref` binding mode with %s", descr)); diff --git a/src/librustpkg/tests.rs b/src/librustpkg/tests.rs index 1ff45aeb833..d130ef249ef 100644 --- a/src/librustpkg/tests.rs +++ b/src/librustpkg/tests.rs @@ -473,13 +473,16 @@ fn test_install_invalid() { } // Tests above should (maybe) be converted to shell out to rustpkg, too - +#[test] fn test_install_git() { let sysroot = test_sysroot(); debug!("sysroot = %s", sysroot.to_str()); let temp_pkg_id = git_repo_pkg(); let repo = init_git_repo(&temp_pkg_id.path); - let repo_subdir = repo.push("mockgithub.com").push("catamorphism").push("test_pkg"); + debug!("repo = %s", repo.to_str()); + let repo_subdir = repo.push("mockgithub.com").push("catamorphism").push("test-pkg"); + debug!("repo_subdir = %s", repo_subdir.to_str()); + writeFile(&repo_subdir.push("main.rs"), "fn main() { let _x = (); }"); writeFile(&repo_subdir.push("lib.rs"), @@ -494,30 +497,28 @@ fn test_install_git() { temp_pkg_id.path.to_str(), repo.to_str()); // should have test, bench, lib, and main command_line_test([~"install", temp_pkg_id.path.to_str()], &repo); + let ws = repo.push(".rust"); // Check that all files exist - debug!("Checking for files in %s", repo.to_str()); - let exec = target_executable_in_workspace(&temp_pkg_id, &repo); + debug!("Checking for files in %s", ws.to_str()); + let exec = target_executable_in_workspace(&temp_pkg_id, &ws); debug!("exec = %s", exec.to_str()); assert!(os::path_exists(&exec)); assert!(is_rwx(&exec)); let _built_lib = built_library_in_workspace(&temp_pkg_id, - &repo).expect("test_install_git: built lib should exist"); - let lib = target_library_in_workspace(&temp_pkg_id, &repo); - debug!("lib = %s", lib.to_str()); - assert!(os::path_exists(&lib)); - assert!(is_rwx(&lib)); + &ws).expect("test_install_git: built lib should exist"); + assert_lib_exists(&ws, temp_pkg_id.short_name, temp_pkg_id.version.clone()); let built_test = built_test_in_workspace(&temp_pkg_id, - &repo).expect("test_install_git: built test should exist"); + &ws).expect("test_install_git: built test should exist"); assert!(os::path_exists(&built_test)); let built_bench = built_bench_in_workspace(&temp_pkg_id, - &repo).expect("test_install_git: built bench should exist"); + &ws).expect("test_install_git: built bench should exist"); assert!(os::path_exists(&built_bench)); // And that the test and bench executables aren't installed - let test = target_test_in_workspace(&temp_pkg_id, &repo); + let test = target_test_in_workspace(&temp_pkg_id, &ws); assert!(!os::path_exists(&test)); debug!("test = %s", test.to_str()); - let bench = target_bench_in_workspace(&temp_pkg_id, &repo); + let bench = target_bench_in_workspace(&temp_pkg_id, &ws); debug!("bench = %s", bench.to_str()); assert!(!os::path_exists(&bench)); } @@ -563,6 +564,7 @@ fn test_package_ids_must_be_relative_path_like() { } +#[test] fn test_package_version() { let local_path = "mockgithub.com/catamorphism/test_pkg_version"; let repo = init_git_repo(&Path(local_path)); @@ -578,28 +580,27 @@ fn test_package_version() { "#[bench] pub fn f() { (); }"); add_git_tag(&repo_subdir, ~"0.4"); + // It won't pick up the 0.4 version because the dir isn't in the RUST_PATH, but... let temp_pkg_id = PkgId::new("mockgithub.com/catamorphism/test_pkg_version"); - match temp_pkg_id.version { - ExactRevision(~"0.4") => (), - _ => fail!(fmt!("test_package_version: package version was %?, expected Some(0.4)", - temp_pkg_id.version)) - } // This should look at the prefix, clone into a workspace, then build. command_line_test([~"install", ~"mockgithub.com/catamorphism/test_pkg_version"], &repo); + let ws = repo.push(".rust"); + // we can still match on the filename to make sure it contains the 0.4 version assert!(match built_library_in_workspace(&temp_pkg_id, - &repo) { + &ws) { Some(p) => p.to_str().ends_with(fmt!("0.4%s", os::consts::DLL_SUFFIX)), None => false }); - assert!(built_executable_in_workspace(&temp_pkg_id, &repo) - == Some(repo.push("build"). + assert!(built_executable_in_workspace(&temp_pkg_id, &ws) + == Some(ws.push("build"). push("mockgithub.com"). push("catamorphism"). push("test_pkg_version"). push("test_pkg_version"))); } +#[test] fn test_package_request_version() { let local_path = "mockgithub.com/catamorphism/test_pkg_version"; let repo = init_git_repo(&Path(local_path)); @@ -1034,6 +1035,30 @@ fn test_extern_mod() { assert!(os::path_exists(&exec_file) && is_executable(&exec_file)); } +#[test] +fn test_import_rustpkg() { + let p_id = PkgId::new("foo"); + let workspace = create_local_package(&p_id); + writeFile(&workspace.push("src").push("foo-0.1").push("pkg.rs"), + "extern mod rustpkg; fn main() {}"); + command_line_test([~"build", ~"foo"], &workspace); + debug!("workspace = %s", workspace.to_str()); + assert!(os::path_exists(&workspace.push("build").push("foo").push(fmt!("pkg%s", + os::EXE_SUFFIX)))); +} + +#[test] +fn test_macro_pkg_script() { + let p_id = PkgId::new("foo"); + let workspace = create_local_package(&p_id); + writeFile(&workspace.push("src").push("foo-0.1").push("pkg.rs"), + "extern mod rustpkg; fn main() { debug!(\"Hi\"); }"); + command_line_test([~"build", ~"foo"], &workspace); + debug!("workspace = %s", workspace.to_str()); + assert!(os::path_exists(&workspace.push("build").push("foo").push(fmt!("pkg%s", + os::EXE_SUFFIX)))); +} + /// Returns true if p exists and is executable fn is_executable(p: &Path) -> bool { use std::libc::consts::os::posix88::{S_IXUSR}; diff --git a/src/libstd/at_vec.rs b/src/libstd/at_vec.rs index 120946ad161..d001e2c6970 100644 --- a/src/libstd/at_vec.rs +++ b/src/libstd/at_vec.rs @@ -255,8 +255,6 @@ pub mod raw { if capacity(*v) < n { let ptr: *mut *mut Box> = transmute(v); let ty = intrinsics::get_tydesc::(); - // XXX transmute shouldn't be necessary - let ty = cast::transmute(ty); return reserve_raw(ty, ptr, n); } } diff --git a/src/libstd/rand/distributions.rs b/src/libstd/rand/distributions.rs index 67be7986c33..6d08b3c84bd 100644 --- a/src/libstd/rand/distributions.rs +++ b/src/libstd/rand/distributions.rs @@ -92,7 +92,7 @@ impl Rand for StandardNormal { let mut x = 1.0f64; let mut y = 0.0f64; - // XXX infinities? + // FIXME #7755: infinities? while -2.0 * y < x * x { x = rng.gen::().ln() / ziggurat_tables::ZIG_NORM_R; y = rng.gen::().ln(); diff --git a/src/libstd/rt/args.rs b/src/libstd/rt/args.rs index 71eae56c894..baaf3d44e79 100644 --- a/src/libstd/rt/args.rs +++ b/src/libstd/rt/args.rs @@ -17,8 +17,8 @@ //! Only valid to call on linux. Mac and Windows use syscalls to //! discover the command line arguments. //! -//! XXX: Would be nice for this to not exist. -//! XXX: This has a lot of C glue for lack of globals. +//! FIXME #7756: Would be nice for this to not exist. +//! FIXME #7756: This has a lot of C glue for lack of globals. use option::Option; diff --git a/src/libstd/rt/comm.rs b/src/libstd/rt/comm.rs index 49cf8c239b7..5d55261a69d 100644 --- a/src/libstd/rt/comm.rs +++ b/src/libstd/rt/comm.rs @@ -46,7 +46,7 @@ struct Packet { payload: Option, } -/// A one-shot channel. +// A one-shot channel. pub struct ChanOne { void_packet: *mut Void, suppress_finalize: bool @@ -681,7 +681,7 @@ impl Clone for SharedPort { } } -// XXX: Need better name +// FIXME #7760: Need better name type MegaPipe = (SharedPort, SharedChan); pub fn megapipe() -> MegaPipe { @@ -1027,9 +1027,8 @@ mod test { fn shared_port_stress() { if util::limit_thread_creation_due_to_osx_and_valgrind() { return; } do run_in_mt_newsched_task { - // XXX: Removing these type annotations causes an ICE - let (end_port, end_chan) = stream::<()>(); - let (port, chan) = stream::<()>(); + let (end_port, end_chan) = stream(); + let (port, chan) = stream(); let end_chan = SharedChan::new(end_chan); let port = SharedPort::new(port); let total = stress_factor() + 100; diff --git a/src/libstd/rt/context.rs b/src/libstd/rt/context.rs index 890ad061a68..5aaddc68383 100644 --- a/src/libstd/rt/context.rs +++ b/src/libstd/rt/context.rs @@ -14,10 +14,10 @@ use libc::c_void; use cast::{transmute, transmute_mut_unsafe, transmute_region, transmute_mut_region}; -// XXX: Registers is boxed so that it is 16-byte aligned, for storing +// FIXME #7761: Registers is boxed so that it is 16-byte aligned, for storing // SSE regs. It would be marginally better not to do this. In C++ we // use an attribute on a struct. -// XXX: It would be nice to define regs as `~Option` since +// FIXME #7761: It would be nice to define regs as `~Option` since // the registers are sometimes empty, but the discriminant would // then misalign the regs again. pub struct Context { @@ -37,7 +37,7 @@ impl Context { /// Create a new context that will resume execution by running ~fn() pub fn new(start: ~fn(), stack: &mut StackSegment) -> Context { - // XXX: Putting main into a ~ so it's a thin pointer and can + // FIXME #7767: Putting main into a ~ so it's a thin pointer and can // be passed to the spawn function. Another unfortunate // allocation let start = ~start; @@ -206,7 +206,7 @@ fn align_down(sp: *mut uint) -> *mut uint { } } -// XXX: ptr::offset is positive ints only +// ptr::mut_offset is positive ints only #[inline] pub fn mut_offset(ptr: *mut T, count: int) -> *mut T { use std::sys::size_of; diff --git a/src/libstd/rt/io/extensions.rs b/src/libstd/rt/io/extensions.rs index d136ddc0fdf..3ce04a902e2 100644 --- a/src/libstd/rt/io/extensions.rs +++ b/src/libstd/rt/io/extensions.rs @@ -229,7 +229,7 @@ pub trait WriterByteConversions { fn write_be_i64(&mut self, n: i64); /// Write a big-endian i32 (4 bytes). - fn write_be_i32(&mut self, n: i32); + fn write_be_i32_(&mut self, n: i32); /// Write a big-endian i16 (2 bytes). fn write_be_i16(&mut self, n: i16); @@ -238,7 +238,7 @@ pub trait WriterByteConversions { fn write_be_f64(&mut self, f: f64); /// Write a big-endian IEEE754 single-precision floating-point (4 bytes). - fn write_be_f32(&mut self, f: f32); + fn write_be_f32_(&mut self, f: f32); /// Write a little-endian u64 (8 bytes). fn write_le_u64_(&mut self, n: u64); @@ -264,7 +264,7 @@ pub trait WriterByteConversions { /// Write a little-endian IEEE754 single-precision floating-point /// (4 bytes). - fn write_le_f32(&mut self, f: f32); + fn write_le_f32_(&mut self, f: f32); /// Write a u8 (1 byte). fn write_u8(&mut self, n: u8); @@ -519,7 +519,7 @@ impl WriterByteConversions for T { u64_to_be_bytes(n as u64, 8u, |v| self.write(v)) } - fn write_be_i32(&mut self, n: i32) { + fn write_be_i32_(&mut self, n: i32) { u64_to_be_bytes(n as u64, 4u, |v| self.write(v)) } @@ -533,7 +533,7 @@ impl WriterByteConversions for T { } } - fn write_be_f32(&mut self, f: f32) { + fn write_be_f32_(&mut self, f: f32) { unsafe { self.write_be_u32(cast::transmute(f)) } @@ -569,7 +569,7 @@ impl WriterByteConversions for T { } } - fn write_le_f32(&mut self, f: f32) { + fn write_le_f32_(&mut self, f: f32) { unsafe { self.write_le_u32(cast::transmute(f)) } @@ -594,7 +594,7 @@ mod test { use super::ReaderUtil; use option::{Some, None}; use cell::Cell; - use rt::io::mem::MemReader; + use rt::io::mem::{MemReader, MemWriter}; use rt::io::mock::MockReader; use rt::io::{read_error, placeholder_error}; @@ -827,48 +827,49 @@ mod test { assert!(buf == ~[10, 11]); } - // XXX: Some problem with resolve here - /*#[test] - fn test_read_write_le() { - let uints = [0, 1, 2, 42, 10_123, 100_123_456, u64::max_value]; + + #[test] + fn test_read_write_le_mem() { + let uints = [0, 1, 2, 42, 10_123, 100_123_456, ::u64::max_value]; let mut writer = MemWriter::new(); - for uints.each |i| { - writer.write_le_u64(*i); + for i in uints.iter() { + writer.write_le_u64_(*i); } let mut reader = MemReader::new(writer.inner()); - for uints.each |i| { + for i in uints.iter() { assert!(reader.read_le_u64() == *i); } } + #[test] fn test_read_write_be() { - let uints = [0, 1, 2, 42, 10_123, 100_123_456, u64::max_value]; + let uints = [0, 1, 2, 42, 10_123, 100_123_456, ::u64::max_value]; let mut writer = MemWriter::new(); - for uints.each |i| { - writer.write_be_u64(*i); + for i in uints.iter() { + writer.write_be_u64_(*i); } let mut reader = MemReader::new(writer.inner()); - for uints.each |i| { + for i in uints.iter() { assert!(reader.read_be_u64() == *i); } } #[test] fn test_read_be_int_n() { - let ints = [i32::min_value, -123456, -42, -5, 0, 1, i32::max_value]; + let ints = [::i32::min_value, -123456, -42, -5, 0, 1, ::i32::max_value]; let mut writer = MemWriter::new(); - for ints.each |i| { - writer.write_be_i32(*i); + for i in ints.iter() { + writer.write_be_i32_(*i); } let mut reader = MemReader::new(writer.inner()); - for ints.each |i| { + for i in ints.iter() { // this tests that the sign extension is working // (comparing the values as i32 would not test this) assert!(reader.read_be_int_n(4) == *i as i64); @@ -893,12 +894,12 @@ mod test { let f:f32 = 8.1250; let mut writer = MemWriter::new(); - writer.write_be_f32(f); - writer.write_le_f32(f); + writer.write_be_f32_(f); + writer.write_le_f32_(f); let mut reader = MemReader::new(writer.inner()); assert!(reader.read_be_f32() == 8.1250); assert!(reader.read_le_f32() == 8.1250); - }*/ + } } diff --git a/src/libstd/rt/io/file.rs b/src/libstd/rt/io/file.rs index a99f5da032c..91289611659 100644 --- a/src/libstd/rt/io/file.rs +++ b/src/libstd/rt/io/file.rs @@ -13,7 +13,7 @@ use super::support::PathLike; use super::{Reader, Writer, Seek}; use super::SeekStyle; -/// # XXX +/// # FIXME #7785 /// * Ugh, this is ridiculous. What is the best way to represent these options? enum FileMode { /// Opens an existing file. IoError if file does not exist. diff --git a/src/libstd/std.rs b/src/libstd/std.rs index 7f22f44a6f8..278df5b170e 100644 --- a/src/libstd/std.rs +++ b/src/libstd/std.rs @@ -198,7 +198,7 @@ mod unicode; #[path = "num/cmath.rs"] mod cmath; -// XXX: This shouldn't be pub, and it should be reexported under 'unstable' +// FIXME #7809: This shouldn't be pub, and it should be reexported under 'unstable' // but name resolution doesn't work without it being pub. pub mod rt; diff --git a/src/libstd/task/mod.rs b/src/libstd/task/mod.rs index 0d2e62a7700..5ffa03dec26 100644 --- a/src/libstd/task/mod.rs +++ b/src/libstd/task/mod.rs @@ -543,7 +543,7 @@ pub fn deschedule() { use rt::local::Local; use rt::sched::Scheduler; - // XXX: What does yield really mean in newsched? + // FIXME #6842: What does yield really mean in newsched? // FIXME(#7544): Optimize this, since we know we won't block. let sched = Local::take::(); do sched.deschedule_running_task_and_then |sched, task| { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 2b977153b03..135f7162157 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5061,12 +5061,19 @@ impl Parser { } } - pub fn parse_str(&self) -> @str { + pub fn parse_optional_str(&self) -> Option<@str> { match *self.token { token::LIT_STR(s) => { self.bump(); - ident_to_str(&s) + Some(ident_to_str(&s)) } + _ => None + } + } + + pub fn parse_str(&self) -> @str { + match self.parse_optional_str() { + Some(s) => { s } _ => self.fatal("expected string literal") } } diff --git a/src/test/compile-fail/attrs-after-extern-mod.rs b/src/test/compile-fail/attrs-after-extern-mod.rs new file mode 100644 index 00000000000..1903786eef8 --- /dev/null +++ b/src/test/compile-fail/attrs-after-extern-mod.rs @@ -0,0 +1,24 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Constants (static variables) can be used to match in patterns, but mutable +// statics cannot. This ensures that there's some form of error if this is +// attempted. + +use std::libc; + +#[nolink] +extern { + static mut debug_static_mut: libc::c_int; + pub fn debug_static_mut_check_four(); + #[cfg(stage37)] //~ ERROR expected item after attributes +} + +pub fn main() {} diff --git a/src/test/compile-fail/issue-6458-1.rs b/src/test/compile-fail/issue-6458-1.rs new file mode 100644 index 00000000000..a54f05ec348 --- /dev/null +++ b/src/test/compile-fail/issue-6458-1.rs @@ -0,0 +1,12 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn foo(t: T) {} +fn main() { foo(fail!()) } //~ ERROR cannot determine a type for this expression: unconstrained type diff --git a/src/test/compile-fail/issue-6458-2.rs b/src/test/compile-fail/issue-6458-2.rs new file mode 100644 index 00000000000..8621b37146f --- /dev/null +++ b/src/test/compile-fail/issue-6458-2.rs @@ -0,0 +1,13 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + fmt!("%?", None); //~ ERROR: cannot determine a type for this expression: unconstrained type +} diff --git a/src/test/compile-fail/issue-6458-3.rs b/src/test/compile-fail/issue-6458-3.rs new file mode 100644 index 00000000000..ac41cc11682 --- /dev/null +++ b/src/test/compile-fail/issue-6458-3.rs @@ -0,0 +1,15 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::cast; + +fn main() { + cast::transmute(0); //~ ERROR: cannot determine a type for this expression: unconstrained type +} diff --git a/src/test/compile-fail/issue-6458-4.rs b/src/test/compile-fail/issue-6458-4.rs new file mode 100644 index 00000000000..131d9c824b6 --- /dev/null +++ b/src/test/compile-fail/issue-6458-4.rs @@ -0,0 +1,17 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn foo(b: bool) -> Result { + Err(~"bar"); //~ ERROR: cannot determine a type for this expression: unconstrained type +} + +fn main() { + foo(false); +} diff --git a/src/test/compile-fail/issue-6458.rs b/src/test/compile-fail/issue-6458.rs new file mode 100644 index 00000000000..8d9c63687ff --- /dev/null +++ b/src/test/compile-fail/issue-6458.rs @@ -0,0 +1,21 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub struct TypeWithState; +pub struct MyState; + +pub fn foo(_: TypeWithState) {} + +pub fn bar() { + foo(TypeWithState); //~ ERROR: cannot determine a type for this expression: unconstrained type +} + +fn main() { +} diff --git a/src/test/compile-fail/issue-6702.rs b/src/test/compile-fail/issue-6702.rs new file mode 100644 index 00000000000..168aa5f9d69 --- /dev/null +++ b/src/test/compile-fail/issue-6702.rs @@ -0,0 +1,19 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct Monster { + damage: int +} + + +fn main() { + let _m = Monster(); //~ ERROR `Monster` is a structure name, but + //~^ NOTE Did you mean to write: `Monster { /* fields */ }`? +} diff --git a/src/test/compile-fail/issue-7013.rs b/src/test/compile-fail/issue-7013.rs new file mode 100644 index 00000000000..fa22665e8c3 --- /dev/null +++ b/src/test/compile-fail/issue-7013.rs @@ -0,0 +1,43 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern mod extra; +use extra::rc::RcMut; + +trait Foo +{ + fn set(&mut self, v: RcMut); +} + +struct B +{ + v: Option> +} + +impl Foo for B +{ + fn set(&mut self, v: RcMut) + { + self.v = Some(v); + } +} + +struct A +{ + v: ~Foo, +} + +fn main() +{ + let a = A {v: ~B{v: None} as ~Foo}; //~ ERROR cannot pack type `~B`, which does not fulfill `Send` + let v = RcMut::from_freeze(a); //~ ERROR instantiating a type parameter with an incompatible type + let w = v.clone(); + v.with_mut_borrow(|p| {p.v.set(w.clone());}) +} diff --git a/src/test/run-pass/issue-5917.rs b/src/test/run-pass/issue-5917.rs index fb6a06875b1..3e588bb53d2 100644 --- a/src/test/run-pass/issue-5917.rs +++ b/src/test/run-pass/issue-5917.rs @@ -8,12 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// xfail-test - use std::io; struct T (&'static [int]); static t : T = T (&'static [5, 4, 3]); fn main () { assert_eq!(t[0], 5); -} \ No newline at end of file +} diff --git a/src/test/run-pass/owned-implies-static.rs b/src/test/run-pass/owned-implies-static.rs new file mode 100644 index 00000000000..4ee55239476 --- /dev/null +++ b/src/test/run-pass/owned-implies-static.rs @@ -0,0 +1,15 @@ +// Copyright 2013 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn f(_x: T) {} + +fn main() { + f(~5); +}